C# 委托/lambda键入和强制如何工作?

C# 委托/lambda键入和强制如何工作?,c#,delegates,lambda,type-inference,anonymous-methods,C#,Delegates,Lambda,Type Inference,Anonymous Methods,我注意到一些例子,在C#中处理lambda函数和匿名委托时,可以使用,也可以不使用。这是怎么回事 class Test : Control { void testInvoke() { // The best overloaded method match for 'Invoke' has some invalid arguments Invoke(doSomething); // Cannot convert anonymous meth

我注意到一些例子,在C#中处理lambda函数和匿名委托时,可以使用,也可以不使用。这是怎么回事

class Test : Control {
    void testInvoke() {
        // The best overloaded method match for 'Invoke' has some invalid arguments
        Invoke(doSomething);

        // Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type
        Invoke(delegate { doSomething(); });

        // OK
        Invoke((Action)doSomething);

        // OK
        Invoke((Action)delegate { doSomething(); });

        // Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
        Invoke(() => doSomething());

        // OK
        Invoke((Action)(() => doSomething()));
    }

    void testQueueUserWorkItem() {
        // The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
        ThreadPool.QueueUserWorkItem(doSomething);

        // OK
        ThreadPool.QueueUserWorkItem(delegate { doSomething(); });

        // The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
        ThreadPool.QueueUserWorkItem((Action)doSomething);

        // No overload for 'doSomething' matches delegate 'WaitCallback'
        ThreadPool.QueueUserWorkItem((WaitCallback)doSomething);

        // OK
        ThreadPool.QueueUserWorkItem((WaitCallback)delegate { doSomething(); });

        // Delegate 'WaitCallback' does not take '0' arguments
        ThreadPool.QueueUserWorkItem(() => doSomething());

        // OK
        ThreadPool.QueueUserWorkItem(state => doSomething());
    }

    void doSomething() {
        // ...
    }
}
这是很多例子。我想我的问题如下:

  • 为什么
    Invoke
    总是拒绝lambda函数或匿名委托,而
    ThreadPool.QueueUserWorkItem
    做得很好

  • “无法将匿名方法转换为类型‘System.Delegate’,因为它不是委托类型”到底是什么意思

  • 为什么
    ThreadPool.QueueUserWorkItem
    接受不带参数的匿名委托,但不接受不带参数的lambda表达式

  • ThreadPool.QueueUserWorkItem
    的签名中有一个特定的委托;调用只有
    委托
    。Lambda表达式和匿名方法只能转换为特定的委托类型

  • 这只是一个错误消息。这意味着,“我不知道您正试图转换为哪种委托类型。”

  • 您使用的是一个完全没有参数列表的匿名方法,该参数列表可以转换为任何不使用out/ref参数的委托类型。如果您尝试了
    delegate(){…}
    (即显式空参数列表),那么它将不起作用。匿名方法的这种“我不在乎参数”的能力是它们唯一的特性,而lambda表达式没有

  • 在简单的任务中,最容易证明所有这些,IMO:

    // Doesn't work: no specific type
    Delegate d = () => Console.WriteLine("Bang");
    
    // Fine: we know the exact type to convert to
    Action a = () => Console.WriteLine("Yay");
    
    // Doesn't work: EventHandler isn't parameterless; we've specified 0 parameters
    EventHandler e1 = () => Console.WriteLine("Bang");
    EventHandler e2 = delegate() { Console.WriteLine("Bang again"); };
    
    // Works: we don't care about parameter lists
    EventHandler e = delegate { Console.WriteLine("Lambdas can't do this"); };
    

    我想我了解代表和兰博达斯。我真是太傻了。好东西一如既往,+1因为“…是lambda表达式所没有的唯一特性。”@recursive,如果您有兴趣了解更多信息,请阅读表达式树。lambda表达式的有趣之处在于,它们实际上是表达式,对所表达的内容具有丰富的描述模型,而不仅仅是将逻辑传递给委托参数的语法快捷方式。这就是像LINQtoSQL这样的魔法得以实现的原因@丹:别忘了lambda语句也是lambda表达式,但不能转换为表达式树。Lambda表达式本身既不是表达式树也不是委托-它们只是一段源代码,可以转换为任何一种。是的,我忘记了Lambda语句。这几天我对语言中能表达的各种东西感到惊讶。我们离ANSI C有很长的路要走。