Implementing IDisposable with empty Dispose for reasons of readability

I like the using(){} statement for its control of scope and for readability. Not only can you create objects, use them and dispose them neatly, but you can also use it like this:

Suppose myInstance is an instance of MyClass from some other place in code - ie a method parameter or something

using (var t = myInstance) {
    t.Foo= "Hello";
    t.Bar= "World";
    ...
}

Definition of MyClass:

public class MyClass : IDisposable
{
   public string Foo {get; set;}
   public string Bar {get; set;}
   ...

   public void Dispose() {}
}

This makes code neater and more readable (I feel) and certainly easier to type. However in order to use this widely you have to implement IDisposable. In this case there's no need for MyClass actually handle anything in Dispose, so its empty.

My question is, is there any drawback to using IDisposable in this way?

I appreciate that there are similar questions already on SO, but I don't think these deal with using IDispose for this purpose (or they refer to specific classes).

EDIT:

OK, so I guess I was being a bit specifc, but there's a wider point here. The using statement is a handy, very neat way to define an instance for a specific length of time, and then you can forget about it. Its seems unfair that this ability should be restricted to IDisposable objects only. Yes there's a certain amount of laziness in not just instancing and then setting to null, but the using block makes it very specific what the instance's scope is. Why shouldn't I be allowed to do it with non IDisposable classes?


When you implement IDisposable you're advertising that your class is special and needs to be disposed off properly. Not only with inline code like that but also when classes hold references to your class. They'll also need to implement IDisposable in order to dispose of your instance. That creates an artificial requirement on the users of your class.

You can use a scope to achieve what you want:

{
  var _ = instance;
  _.Foo = "Hello"; 
  _.Bar = "World"; 
}

Another option is this:

instance.With(_ => {
  _.Foo = "Hello";
  _.Bar = "World"; 
});

...

public static class WithExtensions {
  public static void With<T>(this T instance, Action<T> action) {
    action(instance);
  }
}

This one is better because what's going on is more explicit.

I also see the pain that you have. It'd be better if we could define our own control blocks (like in Nemerle). Although C# doesn't allow that kind of customization, you shouldn't abuse the specific using statement to achieve what you want. You can use lambdas to do that, much in the way I've shown with the With extension method. In fact, that's how some parallel "constructs" were done in the Task Parallel Library.


If your class doesn't need to be disposed, there's no point in using using .

Instead, you can make a normal block:

{ var t = myInstance;
    t.Foo= "Hello";
    t.Bar= "World";
    ...
}

However, I fail to see the purpose.

From a design perspective, you should not implement IDisposable unnecessarily.
Implementing IDisposable tells people who use your class that it uses expensive resources and must be disposed when finished with.
If that's not actually true, you're just making their job harder.


是的,使用块是try / finally块的语法糖。

链接地址: http://www.djcxy.com/p/54458.html

上一篇: C#如何实现Dispose方法

下一篇: 出于可读性原因,使用空Dispose实现IDisposable