是否有可能强制使用"使用"一次性课程?

Zan*_*oni 33 c# dispose idisposable using

我需要强制使用"使用"来处理类的新实例.

public class MyClass : IDisposable
{
   ...
}

using(MyClass obj = new MyClass()) // Force to use "using"
{
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 45

需要确保处理对象的事实表明存在设计缺陷.如果处理是礼貌有效的事情,这很好,但它不应该在语义上是必要的.

没有办法强制通过using语句处理对象.但是,您可以做的是在对象中维护一个标志,指示对象是否被处置,然后编写一个检查该标志的终结器.如果终结器检测到对象没有被丢弃,那么你可以使用终结器,例如,通过failfast终止进程.也就是说,严重惩罚那些忽略处置对象的用户,他们不得不修复他们的错误或停止使用你的对象.

这并不会让我感觉良好,善良或有礼貌,但你是唯一一个知道未能处置对象的可怕后果的人.是否对不遵守你的疯狂规则的人施加惩罚比对他们不遵守规则的后果生活更好是由你来决定的.

  • @Eric:这是一个有趣的巧合,但我今天早些时候在你的博客上发布了一个类似的问题.我要提出的一个意见是,在处理非常有限的资源时,处理在语义上是必要的,这些资源的消耗会对整个过程产生不利影响.如果编译器可以强制执行(或至少警告)某些可支配资源未被确定性地释放,那将是有帮助的 - 为此,我建议可以在实现IDisposable的类型上标记的属性(RequiresRAIISemantics等). (4认同)

Dan*_*ant 21

这很难看,但你可以这样做:

    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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


Tam*_*mas 13

您可以使用Roslyn框架编写自己的警告/错误.您DiagnosticAnalyzer将检查所有构造函数调用,以查看您的类是否正在构建,以及您是否在using语句中.

报告的诊断可以设置为"错误"严重性,并且可以标记为不可配置,这意味着没有人可以将其降级为警告或信息.

此外,如果您正在开发Nuget库,您可能希望将分析器作为开发依赖项发送,并将其添加为分析器nuget包.这将导致您的所有用户被迫处置您的给定类.这种包装称为"代码感知库".

请注意,理论上这可以通过第三方分析器库(例如FxCop)来完成,但是有许多IDisposable实现并不是严格需要处理的,例如MemoryStream,它们Dispose没有做很多,所以这些规则要么有一些白名单机制,要么报告误报.


Mat*_*ato 5

我想知道FXCop是否可以执行该规则?

  • 是的,有 DisposeObjectsBeforeLosingScope 规则。请参阅:http://blogs.msdn.com/codeanalysis/archive/2010/03/22/what-s-new-in-code-analysis-for-visual-studio-2010.aspx (3认同)

Gro*_*ile 5

using语句是编译器从以下转换的简写:

(using DisposableObject d = new DisposableObject()){}
Run Code Online (Sandbox Code Playgroud)

成:

DisposableObject d = new DisposableObject()
try
{

}
finally
{
    if(d != null) d.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

所以你或多或少地会问是否可以强制编写一个调用Dispose for object的try/finally块.

  • *技术上*,它将是`((IDisposable)d).Dispose();`;) (3认同)

Tom*_*ski 1

不,你不能那样做。你甚至不能强迫他们调用 dispose。你能做的最好的事情就是添加一个终结器。请记住,当对象被释放时,终结器将被调用,这取决于运行时。