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)我最近与同事讨论了Dispose实施的价值和类型IDisposable.
我认为即使没有非托管资源可以清理IDisposable,也应该尽快清理类型.
我的同事有不同的想法; 执行IDisposable,如果你没有任何非托管资源为你的类型,最终会被垃圾收集是没有必要的.
我的论点是,如果你有一个想要尽快关闭的ADO.NET连接,那么实现IDisposable并且using new MyThingWithAConnection()有意义.我的同事回答说,在封面下,ADO.NET连接是一种非托管资源.我对他回复的答复是,最终所有东西都是一种非托管资源.
我知道推荐的一次性模式,如果Dispose被调用,你可以免费使用托管和非托管资源,但是如果通过终结器/析构函数调用,则只有免费的非托管资源(前面有关于如何提醒消费者不正确使用您的IDisposable类型的博客)
所以,我的问题是,如果你有一个不包含非托管资源的类型,是否值得实现IDisposable?
我在我的程序上运行了一个堆转储.当我在内存分析器工具中打开它时,我发现java.lang.ref.Finalizerfor org.logicalcobwebs.proxool.ProxyStatement占用了大量内存.为什么会这样?

这段代码......
class Person:
num_of_people = 0
def __init__(self, name):
self.name = name
Person.num_of_people += 1
def __del__(self):
Person.num_of_people -= 1
def __str__(self):
return 'Hello, my name is ' + self.name
cb = Person('Corey')
kb = Person('Katie')
v = Person('Val')
Run Code Online (Sandbox Code Playgroud)
产生以下错误......
Exception AttributeError: "'NoneType' object has no attribute 'num_of_people'" in <bound method Person.__del__ of <__main__.Person object at 0x7f5593632590>> ignored
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有.
class Person:
num_of_people = 0
def __init__(self, name):
self.name = name
Person.num_of_people += 1
def __del__(self):
Person.num_of_people -= 1
def __str__(self): …Run Code Online (Sandbox Code Playgroud) 好吧,众所周知,当GC将Finalize对象标识为垃圾时,它会隐式调用对象上的方法.但如果我这样做会发生什么GC.Collect()?终结者还在执行吗?也许是一个愚蠢的问题,但有人问我这个,我回答"是",然后我想:" 这完全正确吗? "
寻找C#和C++的答案.(在C#中,用'finalizer'替换'析构函数')
执行某些静态finallization的正确方法是什么?
没有静态析构函数.AppDomain.DomainUnload默认域中不会引发该事件.该AppDomain.ProcessExit事件共享所有事件处理程序之间的三秒(默认设置)的总时间,因此它实际上不可用.
请注意:这个问题是关于"析构函数"和"终结器"之间的术语差异及其正确用法.我只提供了在C#和C++/CLI中使用它们的示例,以说明我提出问题的原因.我很清楚它是如何在C#和CLR中实现的,但我问的是术语的正确使用.
在C#世界中,术语"析构函数"和"终结器"似乎几乎可以互换使用,我怀疑是因为C#规范使用"析构函数"一词来描述非确定性清理功能,而CLR文档总是使用单词"终结者",所以在C#领域内他们的意思相同.
但是,在C++/CLI规范中,两者之间存在差异.它允许确定性和非确定性清理,并使用术语"析构函数"作为确定性功能,使用"终结器"作为非确定性功能:
终结器提供非确定性清理.终结器是在垃圾收集期间执行的"最后机会"函数,通常在未执行析构函数的对象上执行.
另外,维基百科对析构函数和终结器的描述表明析构函数和终结符是单独的概念,并且支持C++/CLI规范使用与确定性有关的术语:
与析构函数不同,终结器不是确定性的.当程序显式释放对象时,将运行析构函数.相反,当内部垃圾收集系统释放对象时,执行终结器.
问题:
从计算机科学的角度来看,是否存在"析构函数"和"终结器"之间明确定义的区别,或者术语是否只能在上下文中定义?
如果存在明确定义的差异,那么为什么C#规范会使用"错误"的术语?
我有几个问题,我无法得到正确的答案.
1)当我们没有析构函数时,为什么我们应该在Dispose函数中调用SuppressFinalize.
2)Dispose和finalize用于在对象被垃圾收集之前释放资源.无论是托管资源还是非托管资源我们都需要释放它,那么为什么我们需要在dispose函数中使用一个条件,当我们从IDisposable调用这个重写函数时传递'true':从finalize调用时Dispose并传递false.
请参阅我从网上复制的以下代码.
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除布尔保护的Dispose函数并实现如下所示.
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose();
}
public void Dispose()
{
// Code …Run Code Online (Sandbox Code Playgroud) 有效的Java说:
使用终结器会严重影响性能.
为什么使用终结器破坏对象的速度较慢?
java performance memory-management finalizer object-destruction
finalizer ×10
c# ×7
.net ×4
destructor ×3
idisposable ×2
java ×2
c++ ×1
finalization ×1
memory ×1
oop ×1
performance ×1
proxool ×1
python ×1
python-3.x ×1
static ×1
terminology ×1