我需要强制使用 "using" 来释放一个类的新实例。
public class MyClass : IDisposable
{
...
}
using(MyClass obj = new MyClass()) // Force to use "using"
{
}
我需要强制使用 "using" 来释放一个类的新实例。
public class MyClass : IDisposable
{
...
}
using(MyClass obj = new MyClass()) // Force to use "using"
{
}
需要确保对象被释放的事实表明存在设计缺陷。如果释放是礼貌或高效的事情,那么这很好,但它不应该是语义上必要的。
没有办法通过using
语句强制执行对象的释放。然而,您可以在对象中维护一个指示对象是否被释放的标志,然后编写一个finalizer来检查该标志。如果finalizer检测到对象未被释放,则可以让finalizer通过failfast终止进程。也就是说,严惩忽略释放对象的用户,迫使他们修复错误或停止使用您的对象。
我认为这并不友善、好或礼貌,但只有您知道未释放对象的可怕后果是什么。对于是否对未遵循您疯狂规则的人施加惩罚比忍受其不遵循规则的后果更好,由您决定。
Bitmap
)通过WeakReference
缓存是相对安全的情况外,我看不到不释放所有东西的借口(尽管我发现在构造函数抛出异常的对象上调用Dispose
的困难非常令人恼火)。 - supercatusing
语句,必须依赖于API设计的权宜之计。 - ceztko虽然不太美观,但你可以像这样做:
public sealed class DisposableClass : IDisposable
{
private DisposableClass()
{
}
public void Dispose()
{
//Dispose...
}
public static void DoSomething(Action<DisposableClass> doSomething)
{
using (var disposable = new DisposableClass())
{
doSomething(disposable);
}
}
}
DoSomething()
重命名为DoWithDisposableClass()
并将其移动到工厂。 - LuckyLikeydoSomething
,该怎么办? - denfromufa使用Roslyn框架,您可以编写自己的警告/错误。您的DiagnosticAnalyzer
会检查所有构造函数调用,以查看是否正在构造您的类,以及是否在using
语句中。
报告的诊断可以设置为错误严重性,并且可以标记为不可配置,这意味着没有人可以将其降级为警告或信息。
此外,如果您正在开发Nuget库,可能希望将分析器作为开发依赖项进行打包,并将其添加为分析器nuget包。这将导致所有用户都必须处理您提供的类。这种打包被称为"代码感知库"。
请注意,理论上第三方分析器库也可以执行此操作(例如FxCop),但有许多IDisposable
实现不严格需要处理,例如MemoryStream
,其Dispose
不会有很大作用,因此这些规则要么具有一些白名单机制,要么报告错误的结果。
(using DisposableObject d = new DisposableObject()){}
into:
DisposableObject d = new DisposableObject()
try
{
}
finally
{
if(d != null) d.Dispose();
}
所以你的问题大致是是否可能强制编写一个try/finally块,调用对象的Dispose方法。
((IDisposable)d).Dispose();
;) - Anthony Pegram我想知道 FXCop 是否能够执行这个规则?
不可能的。但是您可以在类的终结器中调用dispose方法(如果实际调用dispose方法,您可以禁止使用它),这样如果未在代码中显式地完成,它就会触发。
此链接将向您展示如何实现终结器/释放模式:
public class ResourceHandle
{
public delegate void ResourceProvider(Resource resource);
private string _parms;
public ResourceHandle(string parms)
{
_parms = parms;
}
public void UseResource(ResourceProvider useResource)
{
Resource resource = new Resource(_parms);
useResource(resource);
resource.Close();
}
}
public class Resource
{
private string _parms;
internal Resource(string parms)
{
// Initialize resource
}
internal void Close()
{
// Do cleaning
}
// Public methods of resource
}
您只能以以下方式使用资源:
public void foo()
{
ResourceHandle resourceHandle = new ResourceHandle("parms");
resourceHandle.UseResource(delegate(Resource resource)
{
// use resource
});
}
正如您所看到的,这里并不真正需要使用IDisposable。
Dispose
方法(通过using
或直接调用),你可以把它的内容放在另一个方法里面,比如析构函数。IDisposable
的模式:// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
// TODO: write code
}
disposed = true;
}
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~ClassName()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
来源: http://msdn.microsoft.com/zh-cn/library/system.gc.suppressfinalize.aspx