2017-02-16 2 views
1

SMTP를 통해 전자 메일을 보내는 것과 관련된 일부 코드를 탐색하는 동안 MSDN에서 다음 스 니펫을 받았습니다.destruct가 여기서 명시 적으로 호출되는 이유는 무엇입니까?

static void CreateMessageWithAttachment(String^ server) 
{ 
    String^ file = L"data.xls"; 

    MailMessage^ message = gcnew MailMessage(L"[email protected]",L"[email protected]",L"Quarterly data report.",L"See the attached spreadsheet."); 

    Attachment^ data = gcnew Attachment(file, MediaTypeNames::Application::Octet); 

    ContentDisposition^ disposition = data->ContentDisposition; 
    disposition->CreationDate = System::IO::File::GetCreationTime(file); 
    disposition->ModificationDate = System::IO::File::GetLastWriteTime(file); 
    disposition->ReadDate = System::IO::File::GetLastAccessTime(file); 

    message->Attachments->Add(data); 

    SmtpClient^ client = gcnew SmtpClient(server); 

    client->Credentials = CredentialCache::DefaultNetworkCredentials; 
    client->Send(message); 

    data->~Attachment(); 
    client->~SmtpClient(); 
} 

여기 왜 소멸자가 호출되는지 궁금합니다. 내가 여기서 뭔가 놓친거야? C++/CLI에서

data->~Attachment(); 
client->~SmtpClient(); 

답변

2

ref 클래스 소멸자 Dispose pattern 통해 추상화이다. 컴파일

다음 C++/CLI 클래스, 다음 C# 코드에

public ref class Test 
{ 
public: 
    Test() { System::Console::WriteLine("ctor"); } 
    ~Test() { System::Console::WriteLine("dtor"); } 

    static void Foo() 
    { 
     auto foo = gcnew Test(); 
     foo->~Test(); 
    } 
}; 

컴파일 해제 (그런 일이 무엇인지 시각화하는 좋은 방법이 그래서 C#을 의미가 기본이 IL 코드에 더 가까운) :

public class Test : IDisposable 
{ 
    public Test() 
    { 
     Console.WriteLine("ctor"); 
    } 

    private void ~Test() 
    { 
     Console.WriteLine("dtor"); 
    } 

    public static void Foo() 
    { 
     new Test().Dispose(); 
    } 

    protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0) 
    { 
     if (A_0) 
     { 
      this.~Test(); 
     } 
     else 
     { 
      this.Finalize(); 
     } 
    } 

    public virtual void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize((object)this); 
    } 
} 

처분 패턴이 컴파일러에 의해 자동으로 구현 된 것을 볼 수 있습니다.

~Test "destructor"가 개인 메서드로 컴파일되고 IDisposable::Dispose 구현이 생성됩니다. 컴파일러는 또한 어떤 이유로 finalizer를 호출합니다.

또한 Foo 정적 메서드에서 볼 수 있듯이 foo->~Test();Dispose으로 호출됩니다. 컴파일러는 foo->Dispose();에 직접 전화 할 수 없습니다.

그러나 표준 접근 방식은 "소멸자"(따라서 Dispose 방법을)를 호출하면 delete 키워드를 사용하는 것입니다 foo가 관리 핸들 때 delete foo;는 C++/CLI에서 foo->~Test();과 동일합니다.

참고이 예에서, 쓰는 대신 :

auto foo = gcnew CppCli::Test(); 
foo->Whatever(); 
delete foo; 

당신은 스택 의미를 사용할 수 및 쓰기 :

Test foo; 
foo.Whatever(); 

foo.~Test();foo 일반처럼, 범위를 벗어나면 호출됩니다 C++.


완전성을 위해 모든 것이 최종 자와 상호 작용하는 방법은 다음과 같습니다. 의 하나를 추가하자

public class Test : IDisposable 
{ 
    public Test() 
    { 
     Console.WriteLine("ctor"); 
    } 

    // This is the real finalizer 
    ~Test() 
    { 
     this.Dispose(false); 
    } 

    // This is what C++/CLI compiles ~Test to 
    // Let's call this MethodA 
    private void ~Test() 
    { 
     Console.WriteLine("dtor"); 
    } 

    // This is what C++/CLI compiles !Test to 
    // Let's call this MethodB 
    private void !Test() 
    { 
     Console.WriteLine("finalizer"); 
    } 

    [HandleProcessCorruptedStateExceptions] 
    protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0) 
    { 
     if (A_0) 
     { 
      this.~Test(); // MethodA, NOT the finalizer 
     } 
     else 
     { 
      try 
      { 
       this.!Test(); // MethodB 
      } 
      finally 
      { 
       base.Finalize(); 
      } 
     } 
    } 

    public virtual void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize((object)this); 
    } 
} 

는 C#에서 추가 혼란의 파이널 라이저는 ~Test()하다는 것을는 private void ~Test()에서 다른입니다 : 이것은 다음과 같은 C#을 -like 코드로 컴파일 해제

public ref class Test 
{ 
public: 
    Test() { System::Console::WriteLine("ctor"); } 
    ~Test() { System::Console::WriteLine("dtor"); } 
    !Test() { System::Console::WriteLine("finalizer"); } 
}; 

을 함수는 소멸자에 대해 C++/CLI 컴파일러가 생성합니다.

+0

감사합니다. 자세한 설명을 주셔서 감사합니다. 정말 도움이됩니다. – Geek

+1

'~ Test()'문법은 표준이 아님을 주목해야합니다. 관리 객체를 처리하는 표준 방법은 C++ 객체와 마찬가지로'delete'를 사용하는 것입니다. –

+0

@DavidYaw, 맞아, 그게 중요한 포인트 야, 고마워! –

관련 문제