我喜欢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类进行此操作?
答案 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",
};