C#2008
我一直在研究这个问题,我仍然对一些问题感到困惑.我的问题如下
我知道如果你处理非托管资源,你只需要一个终结器.但是,如果您使用托管资源来调用非托管资源,您是否仍需要实现终结器?
但是,如果您开发一个不直接或间接使用任何非托管资源的类,您是否可以实现IDisposable该类,以便您的类的客户端可以使用'using statement'?
是否可以接受实现IDisposable,以便您的类的客户端可以使用using语句?
using(myClass objClass = new myClass())
{
// Do stuff here
}
Run Code Online (Sandbox Code Playgroud)我在下面开发了这个简单的代码来演示Finalize/dispose模式:
public class NoGateway : IDisposable
{
private WebClient wc = null;
public NoGateway()
{
wc = new WebClient();
wc.DownloadStringCompleted += wc_DownloadStringCompleted;
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus()
{
// Start the Async's download
// Do other work here
wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
}
private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// …Run Code Online (Sandbox Code Playgroud)在类中的析构函数和Finalize方法之间有什么区别?
我最近发现Visual Studio 2008认为析构函数与Finalize方法同义,这意味着Visual Studio不会让您同时在类中定义这两个方法.
例如,以下代码片段:
class TestFinalize
{
~TestFinalize()
{
Finalize();
}
public bool Finalize()
{
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
在析构函数中调用Finalize时出现以下错误:
以下方法或属性之间的调用不明确:'TestFinalize .~TestFinalize()'和'TestFinalize.Finalize()'
如果对Finalize的调用被注释掉,则会出现以下错误:
类型'ManagementConcepts.Service.TestFinalize'已经定义了一个名为'Finalize'的成员,它具有相同的参数类型
请注意:这个问题是关于"析构函数"和"终结器"之间的术语差异及其正确用法.我只提供了在C#和C++/CLI中使用它们的示例,以说明我提出问题的原因.我很清楚它是如何在C#和CLR中实现的,但我问的是术语的正确使用.
在C#世界中,术语"析构函数"和"终结器"似乎几乎可以互换使用,我怀疑是因为C#规范使用"析构函数"一词来描述非确定性清理功能,而CLR文档总是使用单词"终结者",所以在C#领域内他们的意思相同.
但是,在C++/CLI规范中,两者之间存在差异.它允许确定性和非确定性清理,并使用术语"析构函数"作为确定性功能,使用"终结器"作为非确定性功能:
终结器提供非确定性清理.终结器是在垃圾收集期间执行的"最后机会"函数,通常在未执行析构函数的对象上执行.
另外,维基百科对析构函数和终结器的描述表明析构函数和终结符是单独的概念,并且支持C++/CLI规范使用与确定性有关的术语:
与析构函数不同,终结器不是确定性的.当程序显式释放对象时,将运行析构函数.相反,当内部垃圾收集系统释放对象时,执行终结器.
问题:
从计算机科学的角度来看,是否存在"析构函数"和"终结器"之间明确定义的区别,或者术语是否只能在上下文中定义?
如果存在明确定义的差异,那么为什么C#规范会使用"错误"的术语?
根据这一点,它声明Destructors cannot be inherited or overloaded.在我的情况下,对于所有子类,析构函数将是相同的.这几乎告诉我,我必须在每个子类中定义相同的析构函数.我无法在基类中声明析构函数并使处理具有破坏性?说我有这样的事情:
class A
{
~A()
{
SomethingA();
}
}
class B : A
{
}
B b = new B();
Run Code Online (Sandbox Code Playgroud)
什么时候B被破坏,它的析构函数不会被调用?
我是 C++ 程序员,我是 C# 新手,我写了一个小程序来测试继承,所以这里是源代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Lesson3_Class_inherit_
{
public class Personne
{
public string Name;
public int Age;
public Personne() { }
public Personne(string _Name, int _Age)
{
Name = _Name;
Age = _Age;
Console.WriteLine("Constrcut Personne Called\n");
}
~Personne()
{
Console.WriteLine("Destruct Personne Called\n");
}
};
class Humain : Personne
{
public string Langue;
public Humain(string _Name, int _Age,string _Langue)
{
Console.WriteLine("Constrcut Humain Called\n");
Name = _Name;
Age = _Age;
Langue =_Langue;
} …Run Code Online (Sandbox Code Playgroud) 我知道c#中的Destructors没有执行顺序.
我在几个类中使用以下结构,它是Desturct实例和静态信息:
public class MyClass
{
private static readonly Destructor DestructorObject = new Destructor();
~MyClass()
{
Console.WriteLine("Destructor Called");
}
static void Main(string[] args)
{
var myClass = new MyClass();
}
private sealed class Destructor
{
~Destructor()
{
Console.WriteLine("Static Destructor Called");
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如我上面提到的,Destuctors的顺序是一个统一的.但是当我在许多类中使用这个构造时,我发现,在每个类中都有一个不变的顺序,即使我重新编译应用程序并再次运行它也会保留.
意味着a MyClass1alaways可能首先运行~MyClass1而另一个类MyClass2可能首先运行~Destructor.
由于每个班级显然都有"隐藏"的订单,我能相信吗?
我有这个简单的代码,并试图调用析构函数,但我不能称之为:(
我知道GarbageCollector会在必要时运行,所以我使用了GC.WaitForPendingFinalizers(); 但它也没有用.
这是我的代码:
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Console.WriteLine("{0} / {1} = {2}", 120, 15, calculator.Divide(120, 15)
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Program finishing");
}
}
class Calculator
{
// Constructor
public Calculator()
{
Console.WriteLine("Calculator being created");
}
// Public Divide method
public int Divide(int first, int second)
{
return first / second;
}
// Destructor
~Calculator()
{
Console.WriteLine("Destructor is called");
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的输出:
正在创建的计算器
120/15 = 8
程序完成
我究竟做错了什么?为什么我看不到"析构函数被调用"?
我正在尝试创建一个简单的类,它在不再使用时将自身序列化为磁盘.我现在的代码(见下文).我现在的代码似乎有用,但我对自己的知识并不完全自信,所以我想知道是否有其他人看到这个代码有任何重大问题.
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, this);
byte[] output = Dostuff(ms);
File.WriteAllBytes(DBPATH, output);
}
this.disposed = true;
}
Run Code Online (Sandbox Code Playgroud) 我知道c#中析构函数和终结符的含义和用法的不同.
但是,通常"我应该......"的回答是"不使用析构函数,而是使用MSDN中所示的dispose模式".埃里克利珀写道相当强烈反对使用析构函数不必要的.
但是,这种"模式"主张像这样编写析构函数~T() { Dispose(false); }.陈述的原因是它是一个"后备",在程序员忘记打电话的情况下调用Dispose().当然,这忽略了这样一个事实,即终结者在他们的行动中是不确定的,甚至可能永远不会运行.
因此:
如果我使用处理模式,我还应该提供析构函数吗?顺便说一下,我只处理托管资源(DataContext例如实体框架).
如果我提供了一个析构函数:如果我的类派生自一个IDisposable可能已经提供了析构函数的类,那么我是否应该提供一个析构函数呢?我认为在这种情况下永远不会写析构函数,但是文档说它无论如何都会自动调用基类的析构函数.
这个问题基本上是我们GC.KeepAlive()首先需要的原因.
这就是我们需要它的地方.我们有一些非托管资源的包装器
public class CoolWrapper
{
public CoolWrapper()
{
coolResourceHandle = UnmanagedWinApiCode.CreateCoolResource();
if (coolResourceHandle == IntPtr.Zero)
{
// something went wrong, throw exception
}
}
~CoolWrapper()
{
UnmanagedWinApiCode.DestroyCoolResource(coolResource);
}
public void DoSomething()
{
var result = UnmanagedWinApiCode.DoSomething(coolResource);
if (result == 0)
{
// something went wrong, throw exception
}
}
private IntPtr coolResourceHandle;
}
Run Code Online (Sandbox Code Playgroud)
我们的代码使用该包装器:
var wrapper = CoolWrapper();
wrapper.DoSomething();
Run Code Online (Sandbox Code Playgroud)
如果此代码在Release配置中运行而不是在调试器下运行,那么代码优化器可能会发现在此代码之后实际上没有使用该引用coolResourceHandle,并且在读取内部后该成员变量未被访问(通过托管代码)DoSomething()并将其值传递给非托管代码,因此会发生以下情况:
DoSomething() 叫做coolResourceHandle 被读了~CoolWrapper() 运行UnmanagedWinApiCode.DestroyCoolResource() 运行并且资源被破坏,资源句柄无效UnmanagedWinApiCode.DoSomething() 使用现在引用不存在的对象的值运行(或者可能创建另一个对象并分配该句柄) …c# ×10
destructor ×7
.net ×2
finalize ×2
finalizer ×2
idisposable ×2
inheritance ×2
constructor ×1
dispose ×1
terminology ×1