代码之家  ›  专栏  ›  技术社区  ›  Andrew Hare

我可以用lambda语法忽略委托参数吗?

  •  24
  • Andrew Hare  · 技术社区  · 16 年前

    我很好奇为什么C允许我在某些情况下忽略委托参数,但在其他情况下不忽略。

    例如,允许这样做:

    Action<int> action = delegate { Console.WriteLine("delegate"); };
    

    但这不是:

    Action<int> action = () => Console.WriteLine("lambda");
    

    是否有方法初始化委托并使用lambda忽略参数?我知道我可以向lambda添加一个参数并修复前一行,但这更像是一个与编译器有关的学术问题,以及为什么或如何工作。

    7 回复  |  直到 11 年前
        1
  •  17
  •   tvanfosson    16 年前

    我相信您的第一个示例实际上创建了一个匿名函数,该函数能够接受许多不同的签名,其主体是单个语句 Console.WriteLine... . 因为它可以匹配不同的签名,所以不会导致问题。在第二个示例中,lambda语法本身定义了一个不接受具有相同主体的参数的函数。显然,后者与定义的操作不一致,所以您会得到错误。

    C# Anonymous Method Reference

    有一种情况是 匿名方法提供 在lambda中找不到功能 表达。匿名方法启用 省略参数列表,以及 这意味着匿名方法 可以转换为具有 各种签名。这不是 可以使用lambda表达式。

        2
  •  8
  •   codybartfast    16 年前

    阐述Tvanfosson的答案;C 3.0语言规范(_7.14)中描述了这种行为:

    lambda表达式的行为和 匿名方法表达式是 除以下几点外,相同:

    匿名方法表达式允许 要省略的参数列表 完全,产生可兑换的 委托任何值列表的类型 参数。

    _?lambda表达式允许参数 要省略和推断的类型 而匿名方法表达式 要求参数类型为 明确说明。

    lambda表达式的主体可以 是表达式或语句块 而身体 匿名方法表达式必须是 语句块。

    _?,因为只有lambda表达式可以 有一个表达体,不 匿名方法表达式不能是 已成功转换为 表达式树类型(_§4.6)。

    我想:

    Action<int> action = () => Console.WriteLine("lambda");
    

    相当于:

    Action<int> action = delegate() { Console.WriteLine("delegate"); };
    

    也不会编译。正如DanielPlaisted所说()明确地说没有任何参数。

    如果有相当于代表的人,可能是:

    Action<int> action = => Console.WriteLine("lambda")
    

    它不是很漂亮,我怀疑它不符合lambda表达式的精神。

        3
  •  5
  •   MichaelGG    16 年前

    正如其他人所说,不,不能跳过将参数声明为lambda。但是,为了干净,我建议给他们起个名字,比如uuu。例如

    foo.Click += (_,__) => { ... }
    

    从本质上来说,你不会忽视它们,但你表明你不在乎它们是什么,也不会使用它们。

        4
  •  2
  •   Daniel Plaisted    16 年前

    ()=>…语法显式指定lambda不接受任何参数。也许可以对语言进行修改,使()=>真正意味着“为我推断此lambda的参数”与委托语法的方式相同,但这会使语言更加复杂。在设计新的语言功能时, you start at minus 100 我不认为这个能通过测试。

    可能还有更多的技术原因导致这项工作难以实施(这可能更符合您的要求,但我怀疑是否有技术原因促成了这项决定)。

        5
  •  0
  •   Aaron Powell    16 年前

    我想说它是强制使用lambda表达式的参数。

    以您的第一个示例为例,您将如何与传入的值进行交互,它没有本地表示。

        6
  •  0
  •   Brian Mains    13 年前

    这个怎么样?

    Func<int> lamdapointer = () => TwoArgMethodThatReturnsInt(10,20); // the same method cannot be called with the delegate "NoArgmethodThatReturnsInt"
    
    
    lamdapointer();
    
    Delegate int NoArgmethodThatReturnsInt();
    NoArgmethodThatReturnsInt del = NoArgmethodThatReturnsInt; // only this is possible with delegates
    
    
    public int TwoArgMethodThatReturnsInt(int x,int y)
    {
    return x + y;
    }
    
    public int NoArgmethodThatReturnsInt()
    {
    return 20;
    }
    
        7
  •  0
  •   dzilbers    11 年前

    实际上,委托不指定任何参数,并且适合任何委托方法签名,因此在第一个构造中是允许的。

    lambda表达式()=>…;特别声明了无参数委托,这与操作所需的签名相矛盾-具有单个参数的委托。

    您可能需要使用以下选项之一。

    如果您需要动作有一个参数,您可以通过下一种方式进行(“_u”是标识符名称的合法字符)。

    Action<int> action = _ => Console.WriteLine("lambda");

    或者您可能希望使用以下无参数操作:

    Action action = () => Console.WriteLine("lambda");