使用vs lambda

时间:2010-02-04 13:18:10

标签: c# .net functional-programming

等同吗?

        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("")){

        };

换句话说,我们可以用这种方法替换关键字吗?

8 个答案:

答案 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)

没有。 你正在降低一个语言关键字[意思是编译器可以像弗洛里安指出的那样在它周围做些事情]来进行正常的方法调用。

虽然从语义上讲它们可能是相同的,但编译器不会知道该方法会做什么。 正如我们所知,编译时间检查优于运行时异常。