如何在另一种方法中正确处理本地创建的对象?

How to properly dispose locally created object in another method?

所以我有一个 class 实现了 IDisposable,我有几个方法(在另一个 class 中)遵循以下模式:

public void SomeMethod()
{
    DisposableObject disposableObject = new DisposableObject();

    // Do some stuff with the object

    SomeOtherMethod(disposableObject);
    disposableObject.Dispose();
}

虽然所有这些方法都做不同的事情,但它们都在最后调用 SomeOtherMethod,这会在一次性对象不再需要之前对它做更多的事情。 当我将 disposableObject.Dispose(); 移动到 SomeOtherMethod 时,Visual Studio 给我一条消息说: “使用推荐的处置模式确保 'new DisposableObject()' 创建的对象在所有路径上处置:使用 statement/declaration 或 try/finally

无论我是否使用 ref 关键字将一次性对象传递给 SomeOtherMethod,都会出现此消息。

我的问题是,只要 SomeOtherMethod 调用 Dispose() 就可以处理该对象吗?我假设它会,并且 Visual Studio 继续发送消息只是因为它不是 "aware" 在后续方法中该对象发生的事情,但我很想得到一些确认!

无论在哪里调用Dispose(),都是调用。

不对一次性模式使用语言关键字 using,因此将处置转移到另一种方法中是一种反模式,因此这是一种不好的做法,也是潜在问题的根源。

您只能通过在项目构建设置中添加警告编号来移除警告。

方法 Dispose() 不会破坏对象。

处置模式仅用于释放非托管资源,如 windows 句柄和共享内存。

在调用 Dispose() 之后,您仍然拥有该对象,因此对该对象的引用仍然在托管内存中被引用。

Dispose() 在对象使用结束时调用一次,不再调用。

编译器向您发送警告,因为您违反了使用 using 关键字的模式用法的标准行为。

打破标准可能是问题的根源。

通过让编译器生成 try { ... } finally { Dispose() } 块来确保在正确的位置正确调用 Dispose() 以避免错误,使用一次性对象标准来避免错误。

所以避免直接调用 Dispose()

除非您确定自己在做什么,否则最好使用:

public void SomeMethod()
{
  using ( DisposableObject disposableObject = new DisposableObject() )
  {
    // Do some stuff with the object
    SomeOtherMethod(disposableObject);
  }
}

而且您的代码可能很健壮。

它可能会被释放,也可能不会被释放,这取决于执行是否会到达 Dispose 调用,这是因为在调用 Dispose 之前可以抛出异常。通过 using 关键字显式或隐式使用 try finally 构造可确保在任何情况下都会调用它,这就是 VS 给您警告的原因。

will that object be disposed

抱歉,这是一个毫无意义的问题。 CLR 不会跟踪对象是否调用了“dispose”方法(参见 Will the Garbage Collector call IDisposable.Dispose for me?

作为一般规则,创建问题的方法也应该是自行清理的方法总是更好(可读/可维护/不易出错等)。正如您刚刚发现的那样,此模式还允许编译器自动检查 - 同样,这也是确保您的代码干净利落地编译而没有错误或警告的好规则。

在这种情况下,警告为您提供了几种干净利落地实施的方法;就个人而言,我更喜欢“using”子句(这样就避免了必须显式调用“dispose”),例如:

 public void SomeMethod()
 {
     using (DisposableObject disposableObject = new DisposableObject() )
      {

           // Do some stuff with the object

           SomeOtherMethod(disposableObject);
       }

}