为什么要在此处明确调用 destruct?
Why destruct is being called here explicitly?
在浏览一些与通过 SMTP 发送电子邮件相关的代码时,我在 MSDN 中得到了以下片段。
static void CreateMessageWithAttachment( String^ server )
{
String^ file = L"data.xls";
MailMessage^ message = gcnew MailMessage( L"jane@contoso.com",L"ben@contoso.com",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();
}
我只是想知道为什么他们在这里调用析构函数?我在这里遗漏了什么吗?
data->~Attachment();
client->~SmtpClient();
在 C++/CLI 中,ref
class 析构函数是对 Dispose pattern.
的抽象
以下 C++/CLI class,编译时:
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# 代码(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);
}
}
你可以看到dispose模式是由编译器自动实现的。
~Test
"destructor" 编译为私有方法,并为您生成 IDisposable::Dispose
的实现。出于某种原因,编译器还调用了(空)终结器。
此外,正如您在静态 Foo
方法中看到的那样,foo->~Test();
被简单地转换为对 Dispose
的调用。编译器不会让你直接调用 foo->Dispose();
。
但是调用 "destructor"(因此调用 Dispose
方法)的 标准 方法是使用 delete
关键字:[当 foo
是托管句柄时,=25=] 与 C++/CLI 中的 foo->~Test();
相同。
注意在这个例子中,不是写:
auto foo = gcnew CppCli::Test();
foo->Whatever();
delete foo;
您可以使用堆栈语义并编写:
Test foo;
foo.Whatever();
foo.~Test();
将在 foo
超出范围时调用,就像在常规 C++ 中一样。
为了完整起见,下面是整个过程如何与终结器交互。让我们添加一个:
public ref class Test
{
public:
Test() { System::Console::WriteLine("ctor"); }
~Test() { System::Console::WriteLine("dtor"); }
!Test() { System::Console::WriteLine("finalizer"); }
};
这将反编译为以下类似 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()
,它与 C++/CLI 编译器的 private void ~Test()
函数不同为你的析构函数生成。
在浏览一些与通过 SMTP 发送电子邮件相关的代码时,我在 MSDN 中得到了以下片段。
static void CreateMessageWithAttachment( String^ server )
{
String^ file = L"data.xls";
MailMessage^ message = gcnew MailMessage( L"jane@contoso.com",L"ben@contoso.com",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();
}
我只是想知道为什么他们在这里调用析构函数?我在这里遗漏了什么吗?
data->~Attachment();
client->~SmtpClient();
在 C++/CLI 中,ref
class 析构函数是对 Dispose pattern.
以下 C++/CLI class,编译时:
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# 代码(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);
}
}
你可以看到dispose模式是由编译器自动实现的。
~Test
"destructor" 编译为私有方法,并为您生成 IDisposable::Dispose
的实现。出于某种原因,编译器还调用了(空)终结器。
此外,正如您在静态 Foo
方法中看到的那样,foo->~Test();
被简单地转换为对 Dispose
的调用。编译器不会让你直接调用 foo->Dispose();
。
但是调用 "destructor"(因此调用 Dispose
方法)的 标准 方法是使用 delete
关键字:[当 foo
是托管句柄时,=25=] 与 C++/CLI 中的 foo->~Test();
相同。
注意在这个例子中,不是写:
auto foo = gcnew CppCli::Test();
foo->Whatever();
delete foo;
您可以使用堆栈语义并编写:
Test foo;
foo.Whatever();
foo.~Test();
将在 foo
超出范围时调用,就像在常规 C++ 中一样。
为了完整起见,下面是整个过程如何与终结器交互。让我们添加一个:
public ref class Test
{
public:
Test() { System::Console::WriteLine("ctor"); }
~Test() { System::Console::WriteLine("dtor"); }
!Test() { System::Console::WriteLine("finalizer"); }
};
这将反编译为以下类似 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()
,它与 C++/CLI 编译器的 private void ~Test()
函数不同为你的析构函数生成。