5

진실 / 거짓 대답을 기대하고 있었고 나는 너무 확신하지 못했다는 또 다른 인터뷰 질문.

복제


10 답변


26

finally실행 됨대부분의 시간. 거의 모든 경우입니다. 예를 들어 비동기 예외 (예 :StackOverflowException,OutOfMemoryException,ThreadAbortException) 스레드에서 throw됩니다.finally실행은 보장되지 않습니다. 이는 이유제한된 실행 영역신뢰성이 높은 코드를 작성하기 위해 존재합니다.

인터뷰 목적으로이 질문에 대한 대답은그릇된(나는 아무것도 보증하지 않을 것입니다! 면접관은이 자신을 알지 못할 수도 있습니다!).


  • 매우 흥미 롭습니다. 이전에는 CER에 대해 들어 본 적이 없었습니다. 여기에 그것을 올려 줘서 고마워. - Colin Desmond
  • +1 이것은 자주 놓친 중요한 점입니다! "마침내"라는 말은 위험합니다.항상당신이 지적한 이유로 실행됩니다. 좋은 대답. - Andrew Hare
  • 완전히 동의했다. 문제의 원인은 MSDN 자체라고 생각합니다. 수용된 대답에 언급 된 것과 같은 링크에서이 사실에 대한 인식이 높아야합니다. MSDN 자체가 말하길. "finally try 블록이 어떻게 종료되는지에 관계없이 코드 실행 문 블록을 보장하기 위해 finally가 사용됩니다." 이것이 잘못된 결과입니다. 알아아주 적은이 질문에 예라고 대답하지 않는 사람들. - Mehrdad Afshari
  • 나는 누군가가 그들의 숙제, 훌륭한 대답을하고있는 것을 본다! 매우 흥미로운 기사. - John T
  • 또한 전원이 나가거나, 하드웨어가 오작동하거나, OS가 프로세스를 죽였기 때문에 실행하지 못하는 훨씬 더 일반적인 경우를 잊지 마십시오. 민감한 문구를 절반으로 완성했다면 파일과 OS가 당신을 죽이면 finally 블록은 당신을 구원하지 못한다. - Craig Gidney

7

일반적으로finally블록의 실행이 보장됩니다.

그러나 몇 가지 경우에 오류가 발생하면 CLR을 강제 종료합니다. 이 경우,finally블록이 실행되지 않습니다.

하나의 예제는 StackOverflow 예외가있는 상태입니다.

예 : 아래의 코드에서finally블록이 실행되지 않습니다.

static void Main(string[] args) {
   try {
      Foo(1);
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public static int Foo(int i) {
   return Foo(i + 1);
}

내가 아는 또 다른 경우는 마무리자가 예외를 throw하는 경우입니다. 이 경우 프로세스가 즉시 종료되므로 보증이 적용되지 않습니다.

아래 코드는 문제를 보여줍니다.

static void Main(string[] args) {
   try {
      DisposableType d = new DisposableType();
      d.Dispose();
      d = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public class DisposableType : IDisposable {
   public void Dispose() {
   }

   ~DisposableType() {
      throw new NotImplementedException();
   }
}

두 경우 모두 프로세스가 종료되기 전에catchfinally.

예제가 매우 고안된 것을 인정하지만, 그 예제를 설명하기 위해 만들어졌습니다.

다행히도 어느 누구도 자주 일어나지 않습니다.


  • 흥미로운 점은 두 번째 예제는 다른 / 비보호 스레드에서 발생했기 때문에 예외를 catch하지 않는다는 점입니다. - Matthew Whited
  • +1 StackOverflow 예제를 사용하여 :-) - Josh

6

MSDN에서 직접 스트리밍 :

finally 블록은 다음에 유용합니다.   할당 된 자원 정리   try 블록. 컨트롤은 항상   finally 블록에 관계없이 전달됨   try 블록의 종료 방법에 대한 설명입니다.

catch는 처리하는 데 사용되는 반면   명령문에서 발생하는 예외   블록, 마지막으로   명령문 블록 실행   이전 시도 방법에 관계없이   블록이 종료되었습니다.

http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx



3

예, 마침내 항상 실행됩니다.


3

마침내 항상 처형 될 것이라는 것은 완전히 사실이 아닙니다. 만나다이 대답...에서해킹 된:

두 가지 가능성 :

  • StackOverflowException
  • ExecutingEngineException

finally 블록은 실행되지 않습니다.   StackOverflowException이있을 때   스택에 아무 공간도 없기 때문에   더 이상 코드를 실행할 수 없습니다. 그것은   거기있을 때도 전화하지 마세요.   ExecutingEngineException은 다음과 같습니다.   매우 드물다.

그러나이 두 가지 예외는 복구 할 수없는 예외이므로 기본적으로 프로세스는 종료됩니다.

Mehrdad가 말했듯이, 신뢰할 수있는 try / catch / finally는제한된 실행 영역 (CER). 안MSDN에서 제공합니다.

[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
    public IntPtr m_outputHandle;
}

sealed class MySafeHandle : SafeHandle
{
    // Called by P/Invoke when returning SafeHandles
    public MySafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle AllocateHandle()
    {
        // Allocate SafeHandle first to avoid failure later.
        MySafeHandle sh = new MySafeHandle();

        RuntimeHelpers.PrepareConstrainedRegions();
        try { }
        finally
        {
            MyStruct myStruct = new MyStruct();
            NativeAllocateHandle(ref myStruct);
            sh.SetHandle(myStruct.m_outputHandle);
        }

        return sh;
    }
}


1

일반적으로 finally 블록은 예외가 발생했는지 여부와 예외가 처리되었는지 여부에 관계없이 항상 실행됩니다.

두 가지 예외가 있습니다 (자세한 내용은 다른 답변을 참조하십시오).


0

'Finally'는 예외가 throw되는지 여부에 관계없이 실행됩니다.

열려있는 연결을 닫을 수있는 좋은 장소입니다. 성공 또는 실패한 실행은 여전히 연결을 관리하거나 파일을 열 수 있습니다.


-1

마지막으로 catch 블록을 시도 할 때마다 발생합니다.


-1

마지막으로 블록은 어떤 경우에도 실행되도록 보장됩니다.


-1

마지막으로 항상 실행됩니다. try 블록이 어떻게 작동하는지에 달려 있지 않습니다. try와 cath 모두에 대해 몇 가지 추가 작업을해야한다면 finally 블록을 넣는 것이 좋습니다. 그래서 당신은 항상 그것을 처형 할 수 있습니다.

연결된 질문


관련된 질문

최근 질문