C# 如何在另一个方法中正确处理本地创建的对象?
因此,我有一个实现IDisposable的类,还有几个方法(在另一个类中)遵循以下模式:C# 如何在另一个方法中正确处理本地创建的对象?,c#,idisposable,C#,Idisposable,因此,我有一个实现IDisposable的类,还有几个方法(在另一个类中)遵循以下模式: public void SomeMethod() { DisposableObject disposableObject = new DisposableObject(); // Do some stuff with the object SomeOtherMethod(disposableObject); disposableObject.Dispose(); } 虽
public void SomeMethod()
{
DisposableObject disposableObject = new DisposableObject();
// Do some stuff with the object
SomeOtherMethod(disposableObject);
disposableObject.Dispose();
}
虽然所有这些方法都做了不同的事情,但它们最后都调用了SomeOtherMethod
,这会在不再需要一次性对象之前对其做更多的事情。
当我移动disposableObject.Dispose()时
进入SomeOtherMethod
,Visual Studio给我一条消息说:
“使用建议的dispose模式确保在所有路径上释放由‘new DisposableObject()’创建的对象:使用语句/声明或try/finally”
无论是否使用ref
关键字将一次性对象传递给SomeOtherMethod
,都会显示此消息
我的问题是,只要
SomeOtherMethod
对该对象调用Dispose()
,该对象就会被释放吗?我假设它会,VisualStudio继续发送消息只是因为它不知道在后续方法中该对象发生了什么,但我希望得到一些确认 无论在哪里调用Dispose()
,它都被调用
不使用语言关键字使用
作为一次性模式,因此在另一种方法中移动dispose是反模式的,因此这是一种不好的做法,也是潜在问题的根源
只能通过在项目生成设置中添加警告编号来删除警告
方法Dispose()
不会销毁对象
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
之前抛出异常。使用try
最后
通过使用关键字显式或隐式构造可以确保在任何情况下都会调用它,这就是为什么VS会向您发出警告的原因
那个物体会被处理掉吗
对不起,这是个毫无意义的问题。CLR不跟踪对象是否调用了其“dispose”方法(请参阅)
作为一般规则,创建问题的方法也应该是在其自身之后进行清理的方法,这总是更好(可读/可维护/不易出现错误等)。正如您刚刚发现的,这种模式还允许编译器进行自动检查——同样,这也是一条很好的规则,可以确保代码编译干净,没有错误或警告
在这种情况下,警告为您提供了两种方法来干净地实现这一点;就我个人而言,我更喜欢“使用”条款(这样就不必显式地调用“dispose”),比如:
}无论哪个作用域分配了对象,都应该是该对象的所有者,也应该是该对象的处置者。简单。使用
块在其上放置一个。使用“转移语义”,即赋予SomeOtherMethod
所有权并让其处理对象,可能会导致混淆,最好避免。这就是IDE0067,代码分析警告。它试图告诉您,如果该方法引发异常,该对象可能不会被释放。虽然代码分析通常很难生成有关IDisposable用法的良好诊断,但这一点可能是正确的。您确实喜欢这里的using语句。只有在Dispose()调用后,如果该方法需要很长时间才能执行,则在被调用的方法中处理它才是明智的。“Dispose()
将在对象使用结束时调用一次,不再调用。”。不同意“不再”部分<代码>处置
方法应为@Artur我同意。。。如果Dispose实现正确完成。。。但是不要认为这总是如此,因为在计算机科学中,如果说明书没有明确地引用它,就不应该相信一个实现能够做一些事情…code>IDispose
是一个没有实现的接口,可供所有编码器使用。NET Framework类确实做得很好,但是任何人都可以为自己或为IDispose
和使用关键字来实现好的或坏的Dispose()
。。。因此模式和编译器警告的存在。我不是说规则是否总是满足,我是说你陈述了错误的语句,就像它是一个规则一样。但是你回答的主要问题是它根本没有回答这个问题。OP询问的是将Dispose
调用移动到SomeOtherMethod
中,而不是“实现一次性模式的正确方法”。OP对编译器警告感到恼火。无论在哪里调用dispose,它都被调用。我回答说,对一次性模式不使用language关键字use
,因此在另一种方法中移动dispose,是一种反模式,因此它是一种不好的pr
public void SomeMethod()
{
using (DisposableObject disposableObject = new DisposableObject() )
{
// Do some stuff with the object
SomeOtherMethod(disposableObject);
}