Programing

스위치 블록 내에서 foreach 루프에서 벗어나기

crosscheck 2020. 12. 29. 07:39
반응형

스위치 블록 내에서 foreach 루프에서 벗어나기


스위치 블록 내에서 foreach 루프를 어떻게 중단합니까?

일반적으로 break를 사용하지만 switch 블록 내에서 break를 사용하면 switch 블록에서 빠져 나와 foreach 루프가 계속 실행됩니다.

foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                break;
            }
            break;
        case 2;
            break
    }
}

블록 foreach에서 while 을 벗어나야 할 때 현재하고있는 작업 은 루프 외부에 배치 switchbool값을 true로 설정하고 foreach가 입력 될 때마다 그리고 스위치 블록에 들어가기 전에이 부울의 값을 확인하는 것 입니다. 이 같은:

bool exitLoop;
foreach (var v in myCollection)
{
    if (exitLoop) break;
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
                break;
            }
            break;
        case 2;
            break
    }
}

이것은 작동하지만 나는 이것을하는 더 나은 방법이 있어야한다고 계속 생각합니다.

편집 : @jon_darkstar에서 언급 한 것처럼 PHP 에서 작동하는 정말 깔끔한 방식으로 .NET에서 구현되지 않은 이유 가 궁금하십니까?

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />\n";
        break 1;  /* Exit only the switch. */
    case 10:
        echo "At 10; quitting<br />\n";
        break 2;  /* Exit the switch and the while. */
    default:
        break;
    }
}

이 경우 솔루션은 거의 가장 일반적인 옵션입니다. 즉, 마지막에 출구 확인을 넣을 것입니다.

bool exitLoop;
foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
            }
            break;
        case 2;
            break
    }

    // This saves an iteration of the foreach...
    if (exitLoop) break;
}

다른 주요 옵션은 코드를 리팩터링하고 switch 문과 foreach 루프를 별도의 메서드로 가져 오는 것입니다. 그런 다음 returnswitch 문 내부에서 할 수 있습니다.


부울은 단방향입니다. 다른 하나는 레이블과 고토를 사용하는 것입니다. 나는 사람들이 goto를 근본적인 죄라고 생각하지만 신중하게 (매우 신중하게) 사용하면 유용 할 수 있습니다. 이 경우, foreach 루프의 끝 바로 뒤에 레이블을 배치하십시오. 루프를 종료하려면 해당 레이블로 이동하면됩니다. 예를 들면 :

foreach(var v in myCollection) {
    switch(v.Id) {
        case 1:
            if(true) {
                goto end_foreach;
            }
            break;
        case 2:
            break;
    }
}
end_foreach:
// ... code after the loop

편집 : 어떤 사람들은 리턴을 사용할 수 있도록 루프를 별도의 방법으로 가져 오는 것에 대해 언급했습니다. goto가 필요하지 않고 루프가 포함 된 원래 함수를 단순화하므로 이점이 있습니다. 그러나 루프가 단순하고 루프를 포함하는 함수의 주요 목적이거나 루프가 out 또는 ref 변수를 사용하는 경우에는 제자리에두고 goto를 사용하는 것이 가장 좋습니다. 사실, goto와 레이블이 눈에 띄기 때문에 코드가 복잡하지 않고 명확 해 집니다. 별도의 함수에 넣으면 간단한 코드를 읽기가 더 어려워 질 수 있습니다.


foreach 사이클을 별도의 방법으로 추출하고 return문을 사용할 수 있습니다 . 또는 다음과 같이 할 수 있습니다.

        foreach (object collectionElement in myCollection)
        {
            if (ProcessElementAndDetermineIfStop(collectionElement))
            {
                break;
            }
        }

        private bool ProcessElementAndDetermineIfStop(object collectionElement)
        {
            switch (v.id)
            {
                case 1:
                    return true; // break cycle.
                case 2;
                    return false; // do not break cycle.
            }
        }

솔직히? 이것은 아마도 완전히 유효하고 사용하기에 적절한 유일한 상황 일 것입니다 goto.

foreach (var v in myCollection) {
    switch (v.id) {
        case 1:
            if (true)
                // document why we're using goto
                goto finished;
            break;
        case 2;
            break
    }
}
finished: // document why I'm here

exitLoop플래그와 실제로 다르지 않지만 메서드를 추출하면 더 읽기 쉬울 수 있습니다.

foreach (var v in myCollection)
{
    if(!DoStuffAndContinue(v))
        break;
}


bool DoStuffAndContinue(MyType v)
{
    switch (v.id)
    {
        case 1:
            if (ShouldBreakOutOfLoop(v))
            {
                return false;
            }
            break;
        case 2;
            break;
    }
    return true;
}

명령문 return에서 할 수 있도록 코드를 재구성하는 옵션이 항상 있습니다 switch.


성명 대한 MSDN 문서break따르면 최상위 범위 만 중지 할 수 있습니다.

이 경우는 goto문을 사용 하여 foreach루프 를 떠날 수있는 경우입니다 . goto진술 을 사용하고 싶지 않다면 귀하의 솔루션이 가장 좋은 것 같습니다.

참고로, exitLoop반복이 끝날 플래그를 테스트하여 코드를 개선하여 하나의 열거 자 호출 비용을 절약 할 수 있습니다.


Lame, I know, but that's all you can do about it.

You could always transform it into a while loop and add 'exitLoop' as a condition which must be met. Inside the switch, you can call continue to skip the rest of the current pass and since you would have set exitLoop to false, it'd exit much like break would do. Even though it's not exactly what you're asking, perhaps it's more elegant that way?


Some languages (i know PHP is one, not sure about others) allow you to specify how many control structures you'd like to break out of with

break n;
where 1 is implied if you just do break

break 2 would do what you describe, were it available in C#. I don't believe that's the case so your exit flag is probably the best solution.


Using goto

int[] numbers = { 1, 2, 3, 4, 5 };
foreach (var number in numbers)
{
    switch (number)
    {
        case 1:
            break;
        case 2:
            goto breakLoop;
        default:
            break;
    }

}
breakLoop:
Console.Write("Out of loop");

You can do it with Try/Catch.. But it might not be the best idea in the world, because it causes performance problems and does show nasty lines in the debug window.

try
{ 
foreach (var v in myCollection)
    {
        switch (v.id)
        {
            case 1:
                if (true)
                {
                    throw new SystemException("Break");
                }
                break;
            case 2;
                break;
        }
    }
} catch {}

Transform the switch() statement into a "if() else if() [...] else" series of statements so that the break exits from the foreach() loop.

ReferenceURL : https://stackoverflow.com/questions/4044752/breaking-out-of-a-foreach-loop-from-within-a-switch-block

반응형