出于可读性的原因,使用空Dispose实现IDisposable

时间:2011-03-10 13:50:42

标签: c# idisposable using

我喜欢using(){}语句来控制范围和可读性。您不仅可以创建对象,使用它们并整齐地处理它们,还可以像这样使用它:

假设myInstance是代码中其他地方的MyClass实例 - 即方法参数或其他东西

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

MyClass的定义:

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

   public void Dispose() {}
}

这使得代码更整洁,更易读(我觉得)并且更容易输入。但是,为了广泛使用它,您必须实现IDisposable。在这种情况下,MyClass不需要在Dispose中实际处理任何内容,因此它是空的。

我的问题是,以这种方式使用IDisposable有什么缺点吗?

我很欣赏SO上已经存在类似的问题,但我认为这些问题并不是为了这个目的使用IDispose(或者它们是指特定的类)。

修改

好的,所以我想我有点特别,但这里有更广泛的意义。 using语句是一种方便,非常简洁的方法,可以在特定的时间长度内定义实例,然后您可以忘记它。将这种能力仅限于IDisposable对象似乎是不公平的。是的,不仅仅是实例化,然后设置为null,还有一定程度的懒惰,但是使用块使得它非常具体,实例的范围是什么。 为什么不允许我使用非IDisposable类进行此操作?

6 个答案:

答案 0 :(得分:5)

如果您的课程不需要处理,则使用using毫无意义。

相反,你可以做一个正常的阻止:

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

然而,我没有看到目的。

从设计角度来看,您不应该不必要地实施IDisposable 实施IDisposable告诉使用您的课程的人,它使用昂贵的资源,并且必须在完成后处理 如果事实并非如此,那么你只是在努力工作。

答案 1 :(得分:5)

当您实施IDisposable时,您宣传您的课程是特殊的,需要妥善处理。不仅使用类似的内联代码,而且当类包含对您的类的引用时。他们还需要实现IDisposable才能处理您的实例。这对您班级的用户产生了一种人为的要求。

您可以使用范围来实现您想要的目标:

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

另一种选择是:

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

...

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

这个更好,因为正在进行的更多是显式

我也看到了你的痛苦。如果我们可以定义自己的控制块(比如在Nemerle中)会更好。虽然C#不允许这种自定义,但您不应滥用特定的using语句来实现您的目标。您可以使用lambdas来实现这一点,这与我使用With扩展方法显示的方式非常相似。事实上,这就是Task Parallel Library中某些并行“构造”的完成方式。

答案 2 :(得分:2)

是的,using块是try / finally块的语法糖。

答案 3 :(得分:1)

我不会(ab)使用using来限制方法中变量的范围,除非这些类型确实需要处理 - 它可能只会让人感到困惑。对于您的示例,听起来更像是您想要添加其他方法来更好地构建代码(并且可能获得相同的可读性优势):

public void WorkWithMyInstance(MyInstance t)
{
  t.Foo= "Hello";
  t.Bar= "World";
  ...
}

答案 4 :(得分:0)

你并没有真正按照预期使用界面。根据{{​​3}}:

  

此界面的主要用途是   释放非托管资源。

如果您只是使用IDisposable,那么您可以将其包装在using语句中,我认为这会给您的课程用户留下错误的印象。他们可能会将此代码解释为比其实际做的更多。

我认为意想不到的后果将是混乱。

答案 5 :(得分:0)

你也可以使用这个吗?

var myclass = new MyClass
{
MyProperty1 = "Property1",
MyProperty2 = "Property2",
};