代码之家  ›  专栏  ›  技术社区  ›  John Feminella

为什么匿名委托/lambda不在out/ref参数上推断类型?

  •  16
  • John Feminella  · 技术社区  · 15 年前

    StackOverflow上的几个C问题询问如何使用 out ref 参数。例如,请参见:

    为此,只需指定参数的类型,如:

    public void delegate D(out T p);
    // ...
    D a = (out T t) => { ... };      // Lambda syntax.
    D b = delegate(out T t) { ... }; // Anonymous delegate syntax.
    

    我好奇的是,为什么类型是显式必需的。是不是有特别的原因?也就是说,从编译器/语言的角度来看,为什么不允许以下内容?

    D a = (out t) => { ... };      // Lambda syntax -- implicit typing.
    D b = delegate(out t) { ... }; // Anonymous delegate syntax -- implicit typing.
    

    或者更好,只是:

    D a = (t) => { ... };      // Lambda syntax -- implicit typing and ref|out-ness.
    D b = delegate(t) { ... }; // Anonymous delegate syntax -- implicit typing and ref|out-ness.
    
    2 回复  |  直到 15 年前
        1
  •  17
  •   Eric Lippert    15 年前

    有趣的问题。

    首先,考虑匿名方法和lambda之间的区别。从编译器编写者的角度来看,最重要的区别是lambda可以要求编译器从lambda被分配到的目标中推断参数的类型;C 2匿名方法没有此功能。这个特性看起来差别不大,但实际上它对编译器的实现有重大影响。有关原因的一些想法,请参阅我关于此主题的博客系列:

    http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx

    现在让我们来讨论您的实际问题:为什么我们不能从目标类型推断出lambda的参数的outness/refness。也就是说,如果委托void d(out int x),那么d=x=>x=10;可以推断x是“out int”。

    我不知道为什么我们不能这样做。在编译器内部,out/ref类型与其他类型一样表示为类型。

    然而,功能并不仅仅因为可以完成而完成;它们之所以完成是因为有一个令人信服的理由。对于lambda,首先进行类型推断的最有说服力的原因是linq;我们希望能够对查询理解进行简单的语法转换,将其转换为使用lambda的方法调用,并让方法类型推断引擎计算出所有lambda参数的类型。 生成的LINQ方法中没有一个具有out或ref参数的委托。

    所以,我们没有令人信服的理由来做这个特性。具有out/ref参数的代理相对较少。而分配给这些代表的朗姆达则更为罕见。所以这是一个我们不需要的特性,几乎没有任何人受益。

    C 3是Visual Studio时间表上的“长杆”;我们在任何团队中安排了最多的工作日,这些团队在V中运送了一个组件,这意味着每天我们都会错过时间表,整个 分开 打滑的。这是一种强有力的抑制因素,它抑制了花时间在不必要的功能上,而这些功能对任何人都没有好处。所以这项工作从未完成。

    我同意在这里保持一致是件好事,但这不太可能发生。我们有许多更高的优先事项。

        2
  •  2
  •   Community CDub    7 年前

    Eric Lippert's comment 关于为什么申报和转让 var 变量不能拆分:

    我同意原则上可以这样做,但在实践中它比你的速写要复杂得多。var不仅要求存在初始值设定项,还要求初始值设定项不引用变量。如果你有int m(out int),那么你可以说“int x=m(out x);”,但是你不能说“var x=m(out x);”,因为要在m上进行过载解析,我们需要知道x的类型,这就是我们试图解决的问题。说“var s;if(b)m(out s);else s=0;”是否合法?

    我想你的问题的答案是相似的,比如,

    D a = (out var x) => x = M(out x);
    
    推荐文章