首页 文章

委托/ lambda打字和强制如何工作?

提问于
浏览
9

我已经注意到一些在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表达式?

1 回答

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

    • 这只是一个错误的错误消息 . 这意味着,“我不确切地知道您要转换为哪种委托类型 . ”

    • 您正在使用一个没有参数列表的匿名方法,可以将其转换为不使用out / ref参数的任何委托类型 . 如果您尝试 delegate() { ... } (即显式空参数列表),那么它将无法工作 . 匿名方法的这种"I don't care about parameters"能力是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"); };
    

相关问题