Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 确保对类成员/字段调用Dispose的正确方法是什么?_C#_.net_Idisposable - Fatal编程技术网

C# 确保对类成员/字段调用Dispose的正确方法是什么?

C# 确保对类成员/字段调用Dispose的正确方法是什么?,c#,.net,idisposable,C#,.net,Idisposable,我有一个类(myClass),它有一个从IDisposable派生的类成员(myDisposableMem),因此有一个Dispose()方法。如果它是一个局部变量,我可以使用(…){…}来确保对这个对象调用Dispose()。但它是一个班级成员。确保对成员调用Disposed的正确方法是什么?我可以想出两种方法: 1) 在类中添加finallize(),然后在内部调用myDisposableMem.Dispose() 或 2) 使我的类从IDisPoble继承: public class my

我有一个类(myClass),它有一个从IDisposable派生的类成员(myDisposableMem),因此有一个Dispose()方法。如果它是一个局部变量,我可以使用(…){…}来确保对这个对象调用Dispose()。但它是一个班级成员。确保对成员调用Disposed的正确方法是什么?我可以想出两种方法:

1) 在类中添加finallize(),然后在内部调用myDisposableMem.Dispose()

2) 使我的类从IDisPoble继承:

public class myClass : IDisposable
{
 ...
  public void Dispose()
  {
    myDisposableMem.Dispose();
  }
}
void main ()
{
  using (myClass myObj = new MyClass())
  {
   .... 
  }
}

或者有更好的方法吗?

您发布的代码有不同的用途

public class myClass : IDisposable
{
  ...
  public void Dispose()
  {
    myDisposableMem.Dispose();
  }
}
这意味着,当有人(您自己或其他任何人)调用您的类的Dispose方法时,它也会调用
myDisposableMem
上的Dispose方法,这是正确的做法(我强烈建议您,如果
myClass
上有其他一次性成员,您也可以将其包含在此处……)

另一方面

void main ()
{
  using (myClass myObj = new MyClass())
  {
    .... 
  }
}
这意味着
myObj
尚未成为该类的成员,并且它将仅在using语句中可用,稍后将被释放

这是两种不同的情况,您必须确定哪种情况适用于您。如果您已经在类中拥有该成员,我强烈建议您在
myClass
本身被释放之前不要释放它,除非您绝对确定没有其他人会使用它,并且需要大量资源才能将其留在那里

对实际代码/场景的更多了解可能会帮助我们告诉您应该使用哪种方法

还要考虑到实际工作情况,这可能会对您有所帮助


在我看来,我不能保证我就在这里,Dispose()方法确保实现对象在应用程序无法访问之前释放其使用的所有资源,但这不会将其从堆栈中移除,同时在实现时调用finalize方法,垃圾收集期间。

终结和实现
IDisposable
不是两个单独的选项;它们应该始终一起完成。您应该始终实现
IDisposable
,并在
Dispose()
中清理您的资源,以便用户能够确保及时清理非托管资源。您应该始终通过调用来结束
Dispose()
方法,以确保不会调用其终结器,原因稍后将解释

在实现
IDisposable
时,应该始终实现
~MyObject()
。它的目的是为垃圾收集器提供一种方法,确保您的对象始终被处理掉,以防使用它的人自己无法处理它。如果终结器所做的不仅仅是调用
this.Dispose()
,那么您可能使用不正确。不。请看下面的Ilian Pinzon的评论,我显然有一些文档要再次阅读

这实际上只是一个安全网。理想情况下,终结器实际上不应该被调用,因为对象总是显式地被释放。当垃圾收集器调用它时,它将被迫跳过收集该对象。这反过来意味着它将被传递到第二代垃圾收集器。这反过来意味着该对象将在内存中停留更长的时间,最终清理成本更高

以及关于如何做的更多信息

也就是说,最好的选择是将这些一次性对象从类上下文中取出,并尽可能使它们成为方法变量


例如,如果您有一个连接到数据库的类,则不要将
SqlConnection
的主实例存储为字段。相反,让您的公共方法创建它们自己的连接,并根据需要将它们传递给私有方法。这有两个优点:首先,这意味着您可以使用块在
中声明您的
SqlConnections
,并使用它来完成。第二,如果您需要的话,摆脱“全局”状态将有助于线程安全。(SqlConnection还有其他一些特定的优点,但这些都是通用的。)

如果对象或代码段包含引用,则称其“拥有”一个
IDisposable
,并且没有理由相信任何其他对象或代码段会在其上调用
Dispose
。拥有本地变量中的IDisposable的代码通常必须在放弃该变量之前,对其调用Dispose,或者将其交给期望获得所有权的其他代码或对象。拥有存储在字段中的
IDisposable
的对象通常必须实现
IDisposable
本身;它的
Dispose
方法应该检查字段是否为空,如果不是空,则对其调用
Dispose

请注意,仅保留对
IDisposable
的引用并不意味着应该对其调用
Dispose
。如果有合理的预期,没有其他代码会这样做,那么只能在IDisposable
上调用
Dispose

只有当对象能够以一种在未知线程上下文中既有用又安全的方式执行某些清理时,才应该覆盖
Finalize
。通常,对象不应在
Finalize
方法中的其他
IDisposable
对象上调用
Dispose
,因为尽管(与某些来源声称的相反)这些对象保证存在,但以下条件之一最有可能适用:

  • 另一个对象可能仍在某处使用,在这种情况下,对其调用“Dispose”是不安全的。
  • 另一个对象可能已经调用了“Finalize”方法,在这种情况下,“Dispose”充其量是多余的,可能是u