代码之家  ›  专栏  ›  技术社区  ›  SharePoint Newbie

编写一个接受lambda表达式的方法

  •  24
  • SharePoint Newbie  · 技术社区  · 16 年前

    我有一个具有以下签名的方法:

     void MyMethod(Delegate d){};
     void MyMethod(Expression exp){};
     void MyMethod(object obj){};
    

    但是,这无法编译:

    MyMethod((int a) => a)
    

    "Cannot convert lambda expression to type 'object' because it is not a delegate type"
    

    为什么这样不行?

    编辑:我知道这是可行的。我认为,在本例中,编译器将lambda表达式编译为delgate。

    void MyMethod(Func<int, int> d){};
    

    亲切问候,,

    6 回复  |  直到 16 年前
        1
  •  21
  •   Maximilian Mayerl    16 年前

    因为类型System.Delegate不是“Delegate”。这只是基类。您必须使用具有正确签名的委托类型。按如下方式定义您的方法:

    void MyMethod(Func<int, int> objFunc)
    

    编辑:

    MyMethod(object)不起作用,因为lambda表达式本身没有类型,但该类型是从分配给它的位置的类型推断出来的。所以这个对象也不起作用。您必须使用具有正确签名的委托类型。

        2
  •  14
  •   user1228 user1228    16 年前
    void MyMethod(Action<int> lambdaHereLol)
    {
        lambdaHereLol(2);
    }
    

    使用中:

    var hurrDurr = 5;
    MyMethod(x => Console.Write(x * hurrDurr));
    

    x 是一个 int (我的例子很简单,但没有任何东西表明它不会更复杂、更难确定)。因此,我必须更明确地定义接受lambda的方法。

        3
  •  3
  •   Joren    16 年前

    兰姆达式 (int a) => a 将适合任何接受 int 并返回一个 int Func<int,int> 这只是一个示例,您可以轻松地用 delegate int Foo(int x); int 并返回一个 double ,因为lambda( a )可隐式转换为 双重的

    为了使lambda能够分配给它所适合的所有委托类型,lambda本身并没有固有的类型。相反,只要有可能,它将采用您正在使用的代理的类型。( 无法分配给 Func<byte, byte> 当然可以。)

    而两者 Func<int, int> Foo Delegate ,lambda不能直接转换为 因为现在还不清楚它的实际签名是什么。之后 Delegate d = (int a) => a d Func<int,int> ,甚至 Func<int, double> ? 所有这些都是有效的可能性,编译器不知道您的意图。这可能是一个最好的猜测,但C#不是那种进行这种猜测的语言。这也是为什么你不能做类似的事情 var = (int a) => a .

    我确实认为编译器给出的错误消息 Delegate d = (int a) => a;

    无法将lambda表达式转换为类型“System.Delegate”,因为它不是委托类型

    代表 是一种委托类型,但这不是工作方式。:)

        4
  •  2
  •   Andrew Hare    16 年前

    试试这个:

    void MyMethod(Action<int> func) { }
    

    您需要将强类型委托作为方法的参数。其他调用失败的原因是C#编译器不允许将lambda表达式传递给需要 Object Delegate .

    当您将lambda传递给像我上面所展示的那样的函数时,编译可以安全地假设您希望lambda表达式转换为特定的委托类型,并这样做。

        5
  •  0
  •   Noldorin    16 年前

    您需要显式地将委托对象强制转换为编译器的性质 Delegate 将其作为类型的参数传递时 代表 . 事实上,lambda表达式使事情更加复杂,因为在这种情况下它们不能隐式转换为委托。

    您需要的是双重演员阵容,例如:

    MyMethod((Delegate)(Func<int, int>)((int a) => a));
    

    当然,这与方法签名相对应:

    void MyMethod(Delegate d);
    

    根据您的情况,您可能需要定义类型为的参数 Func<int> 而不是 代表 (尽管我会犹豫是否增加过载,只是因为它增加了不必要的复杂性)。

        6
  •  0
  •   SoftMemes    16 年前

    失败的原因与“object del=(int a)=>a”甚至“var del=(int a)=>a”之类的表达式失败的原因相同。您可能认为编译器可以找出lambda表达式的类型,因为您显式地给出了参数的类型,但是即使知道表达式接受int并返回int,也可以将它转换为许多委托类型。Func委托类型是此类泛型函数最常用的类型,但这只是一种约定,编译器对此一无所知。

    您需要做的是将lambda表达式强制转换为具体的委托类型,以便让编译器使用普通强制转换语法(Func)((int a)=>a)或使用委托构造函数语法new Func((int a)=>a)选择委托重载。

    此外,通常不希望使用非类型化委托类,除非您需要根据它接受的参数数量以不同的方式调用某些对象。对于回调之类的事情,接受Func或Action几乎总是更好的。