等同吗?
public static void Using<T>(this T disposable, Action<T> action)
where T:IDisposable
{
try {
action(disposable);
}
finally {
disposable.Dispose();
}
}
new SqlConnection("").Using(conn => {
});
using(var conn = new SqlConnection("")){
};
换句话说,我们可以用这种方法替换关键字吗?
答案 0 :(得分:19)
我不认为这是一个特别好的主意,因为它也允许我们写
var conn = new SqlConnecction("");
conn.Using(c => /* do something with c */);
conn.Open();
这会编译,但当你到达最后一行时,它会抛出一个ObjectDisposedException。
在任何情况下,using
编码习惯都是众所周知的,那么为什么让你的开发人员更难以阅读你的代码呢?
答案 1 :(得分:10)
我注意到你的方法没有“使用”语句所做的所有。例如,它没有引入新的局部变量声明空间,在该空间中可以声明保留在资源上的变量。
也不允许一次性声明多个相同类型的一次性资源。
最后,它似乎并没有特别优雅地与自己构成。关于“使用”作为陈述的一个好处是你可以说:
using(something)
using(someotherthing)
using(somethirdthing)
{
use all three, they'll all get disposed
}
您的提案会怎样?
something.Using(
x=>someotherthing.Using(
y=>somethirdthing.Using(
z=> { use all three } )));
坦率地说,有点严重。
答案 2 :(得分:2)
一个限制:您无法访问lambda中包含方法的参数。
答案 3 :(得分:2)
using
语句会检查disposable
是否为null
。除了在运行时,您将获得大致相同的行为(除了额外的stack frame和委托调用之外)。
答案 4 :(得分:2)
我不想使用它的一些原因。
编译时间万无一失
using (var foo=new Bar())
{
foo=new Bar();// throws an error at compile time
}
实施IDisposable的结构
在对它们调用接口方法时,会对实现接口的结构进行装箱。 using语句足够智能,可以在编译时识别其目标是结构,并放弃装箱。
答案 5 :(得分:1)
正如理查德所说,在创建一次性对象和尝试的开始之间有一个额外的方法调用。这会增加发生异步异常的时间范围,从而导致您的一次性对象无法处理。但是,这不是一个大问题,因为实现IDisposable的类型不应该在构造函数中获取它们的资源(SqlConnection在调用Open()方法期间获取其资源)。
因此,虽然您编写using语句的新方式可行,但它使得其他开发人员的阅读更加困难,并且很容易被Mark Seemann指出的方式滥用。
那么你可以用using扩展方法替换using关键字吗?是。你应该这样做吗?否。
答案 6 :(得分:0)
几乎 功能等效,但实际上它并没有带来任何好处。 “传统”using
语句的语义是众所周知的和标准的。虽然您的方法可能表现相同(尽管存在一些差异),但它会带来不必要的开销和复杂性 - 您不仅需要自己复制代码的其他方法调用,而且编译器会自动生成这些调用。
答案 7 :(得分:0)
没有。 你正在降低一个语言关键字[意思是编译器可以像弗洛里安指出的那样在它周围做些事情]来进行正常的方法调用。
虽然从语义上讲它们可能是相同的,但编译器不会知道该方法会做什么。 正如我们所知,编译时间检查优于运行时异常。