[c#] ‘continue’문이 ‘finally’블록 안에있을 수없는 이유는 무엇입니까?

나는 문제가 없습니다. 그냥 궁금 해요. 다음 시나리오를 상상해보십시오.

foreach (var foo in list)
{
    try
    {
         //Some code
    }
    catch (Exception)
    {
        //Some more code
    }
    finally
    {
        continue;
    }
}

컴파일러 오류 CS0157이 발생하므로 컴파일되지 않습니다 .

제어는 finally 절의 본문을 벗어날 수 없습니다.

왜?



답변

finally블록은 예외 발생 여부에 관계없이 실행됩니다. 예외가 발생하면 도대체 continue어떻게할까요? 잡히지 않은 예외가 다른 함수로 제어를 이전하기 때문에 루프 실행을 계속할 수 없습니다.

예외가 발생하지 않더라도 finally는 try / catch 블록 내의 다른 제어 전송 문이 실행될 때 실행됩니다 ( return예 : 같은 문제가 발생하는).

요컨대, finally그것 의 의미론으로 인해 finally블록 내부 에서 외부 로 제어를 전송하는 것은 의미 가 없습니다 .

의도 된 동작을 더 명확하게 만드는 간단한 해결 방법이 있기 때문에 일부 대체 의미 체계로이를 지원하는 것은 도움이되는 것보다 더 혼란 스러울 것입니다. 따라서 오류가 발생하고 문제에 대해 올바르게 생각해야합니다. C #에서 계속되는 것은 일반적인 “성공의 구덩이에 던져 넣는”아이디어입니다.

C #, 당신, 그리고 성공한다면

예외를 무시하고 (나쁜 생각이 아닌 경우가 많음) 루프를 계속 실행하려면 catch all 블록을 사용하십시오.

foreach ( var in list )
{
    try{
        //some code
    }catch{
        continue;
    }
}

continue포착되지 않은 예외가 발생하지 않을 때만 원하는 경우 continuetry-block 외부에 두십시오 .


답변

다음은 신뢰할 수있는 출처입니다.

continue 문은 finally 블록을 종료 할 수 없습니다 (섹션 8.10). finally 블록 내에서 continue 문이 발생하면 continue 문의 대상은 동일한 finally 블록 내에 있어야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.

MSDN, 8.9.2 에서 가져온 것입니다 . continue 문 .

문서는 다음과 같이 말합니다.

finally 블록의 문은 제어가 try 문을 떠날 때 항상 실행됩니다. 제어 전송이 정상적인 실행의 결과로 발생하거나 break, continue, goto 또는 return 문을 실행 한 결과로 발생하거나 또는 try 문에서 예외를 전파 한 결과로 발생하는 경우에 해당됩니다. finally 블록을 실행하는 동안 예외가 발생하면 예외는 다음 엔 클로징 try 문으로 전파됩니다. 전파중인 다른 예외가있는 경우 해당 예외가 손실됩니다. 예외를 전파하는 프로세스는 throw 문에 대한 설명에서 자세히 설명합니다 (섹션 8.9.5).

여기에서 8.10 try 문 .


답변

말이된다고 생각할 수도 있지만 실제로 는 말이되지 않습니다 .

foreach (var v in List)
{
    try
    {
        //Some code
    }
    catch (Exception)
    {
        //Some more code
        break; or return;
    }
    finally
    {
        continue;
    }
}

예외가 발생할 때 중단 또는 계속 을 수행 할 의도는 무엇입니까 ? C # 컴파일러 팀은 break또는 continue. 대신, 그들은 개발자 상황이 .NET에서 제어권을 이전하는 것이 모호하다고 불평하기로 결정했습니다 finally block.

따라서 컴파일러가 다른 것을 가정하는 것보다 자신이하려는 일을 명확하게 밝히는 것이 개발자의 임무입니다.

이것이 컴파일되지 않는 이유를 이해하기를 바랍니다!


답변

다른 사람들이 말했듯이 예외에 초점을 맞추는 것은 실제로 제어 전송의 모호한 처리에 관한 것입니다.

당신은 아마도 다음과 같은 시나리오를 생각하고있을 것입니다.

public static object SafeMethod()
{
    foreach(var item in list)
    {
        try
        {
            try
            {
                //do something that won't transfer control outside
            }
            catch
            {
                //catch everything to not throw exceptions
            }
        }
        finally
        {
            if (someCondition)
                //no exception will be thrown, 
                //so theoretically this could work
                continue;
        }
    }

    return someValue;
}

이론적으로는 제어 흐름을 추적하고 “좋아”라고 말할 수 있습니다. 예외가 발생하지 않으며 제어가 전송되지 않습니다. 그러나 C # 언어 디자이너는 다른 문제를 염두에 두었습니다.

던진 예외

public static void Exception()
{
    try
    {
        foreach(var item in list)
        {
            try
            {
                throw new Exception("What now?");
            }
            finally
            {
                continue;
            }
        }
    }
    catch
    {
        //do I get hit?
    }
}

공포의 고토

public static void Goto()
{
    foreach(var item in list)
    {
        try
        {
            goto pigsfly;
        }
        finally
        {
            continue;
        }
    }

    pigsfly:
}

반환

public static object ReturnSomething()
{
    foreach(var item in list)
    {
        try
        {
            return item;
        }
        finally
        {
            continue;
        }
    }
}

헤어짐

public static void Break()
{
    foreach(var item in list)
    {
        try
        {
            break;
        }
        finally
        {
            continue;
        }
    }
}

이 동안 그래서 결론적으로, 그래, 이다 약간의 사용 a의 가능성 continue제어가 전송되지 않는 상황에서,하지만 좋은 거래 (대부분?)의 경우는 예외 또는 포함 return블록. 언어 디자이너는 이것이 너무 모호하고 컴파일 타임 에 제어 흐름이 전송되지 않는 경우 에만continue 사용 된다는 것을 보장하기가 불가능하다고 느꼈습니다 .


답변

일반적으로 블록 continue에서 사용할 때 의미가 없습니다 finally. 이것 좀보세요 :

foreach (var item in list)
{
    try
    {
        throw new Exception();
    }
    finally{
        //doesn't make sense as we are after exception
        continue;
    }
}


답변

“이것은 컴파일되지 않을 것이며 완전히 말이되는 것 같습니다.”

글쎄, 그렇지 않다고 생각합니다.

말 그대로 있으면 catch(Exception)finally (그리고 아마도)가 필요하지 않습니다 continue.

더 현실적 catch(SomeException)일 때 예외가 포착되지 않으면 어떻게해야합니까? 당신 continue은 한 방향으로 가고 싶어하고, 예외는 다른 것을 처리합니다.


답변

finally 블록의 본문을 떠날 수 없습니다. 여기에는 중단, 반환 및 귀하의 경우 계속 키워드가 포함됩니다.