是否存在不依赖于IDisposable的使用模式?

Kei*_*ons 3 c# idisposable using misuse

我想创建一个内部消息系统,可以告诉我一些代码被调用的持续时间.我在考虑易用性,以使SystemMessage类实现IDisposable.

我会在SystemMessage的构造函数中设置一个时间戳,如果调用了Dispose,我可以计算出持续时间.

问题是我不希望GC对象.我希望它作为MessageCollection的一部分留在身边.

在C#中是否有另一个构造可以在没有踩到IDisposable的预期功能的情况下为我提供Using语句的可用性.

Using (message = Collection.CreateNewMessage("FileDownlading"))
{
    // I wonder how long it is taking me to download this file in production?
    // Lets log it in a message and store for later pondering.
    WebClass.DownloadAFile("You Know This File Is Great.XML");
}
// we fell out of the using statement, message will figure out how long
// it actually took to run.
// This was clean and easy to implement, but so wrong?
Run Code Online (Sandbox Code Playgroud)

Mar*_*ett 5

问题是我不希望GC对象.我希望它作为MessageCollection的一部分留在身边.

调用Dispose不会导致对象被GC控制 - 当GC执行扫描并且没有任何内容引用它时会发生这种情况.如果您仍然通过MessageCollection引用该对象,它将会坚持下去.

Dispose可以防止它被终结,但由于你没有使用Dispose来清理资源,你将没有Finalizer而你也不会关心.

所以,真正唯一的问题是令人困惑的语义围绕让你的calss实现IDisposable,即使没有资源可以处理.

就个人而言,我不认为这是一个问题.如果消费者呼叫Dispose,那么很好 - 他们得到时间记录.如果他们不这样做,那么他们就不会获得itme邮票,而最糟糕的情况是他们会得到一个FxCop违规行为.

然而,它有点不直观 - 所以如果这是供公众使用的话,我建议提供更多可发现的替代方案,例如:

// C# 3+ lambda syntax
Collection.CreateNewMessage("FileDownlading", () => {
    // I wonder how long it is taking me to download this file in production?    
    // Lets log it in a message and store for later pondering.    
    WebClass.DownloadAFile("You Know This File Is Great.XML");
});

// C# 2 anonymous delegate syntax
Collection.CreateNewMessage("FileDownlading", delegate() {
    // I wonder how long it is taking me to download this file in production?    
    // Lets log it in a message and store for later pondering.    
    WebClass.DownloadAFile("You Know This File Is Great.XML");
});

// Method
void CreateNewMessage(string name, Action action) {
   StopWatch sw = StopWatch.StartNew();
   try {
      action();
   } finally {
      Log("{0} took {1}ms", name, sw.ElapsedMilliseconds);
   }
}
Run Code Online (Sandbox Code Playgroud)

这将运行和时间一个行动代表.