委托/lambda 类型和强制如何工作?

发布于 2024-09-25 06:17:06 字数 1945 浏览 5 评论 0原文

我注意到在处理 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() {
        // ...
    }
}

嗯,这样的例子有很多。我想我的问题如下:

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

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

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

I've noticed some examples of things that work and don't work when dealing with lambda functions and anonymous delegates in C#. What's going on here?

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() {
        // ...
    }
}

Well that's a lot of examples. I guess my questions are the following:

  1. Why does Invoke always refuse a lambda function or an anonymous delegate, yet ThreadPool.QueueUserWorkItem does just fine?

  2. What the heck does "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type" mean anyway?

  3. Why does ThreadPool.QueueUserWorkItem accept an anonymous delegate with no parameters, but not a lambda expression with no parameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

[浮城] 2024-10-02 06:17:06
  1. ThreadPool.QueueUserWorkItem 在其签名中有一个特定委托; Invoke 只有Delegate。 Lambda 表达式和匿名方法只能转换为特定委托类型。

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

  3. 您使用的匿名方法根本没有参数列表,它可以转换为任何不使用 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. ThreadPool.QueueUserWorkItem has a specific delegate in its signature; Invoke just has Delegate. Lambda expressions and anonymous methods can only be converted to a specific delegate type.

  2. It's just a bad error message. It means, "I don't know exactly which delegate type you're trying to convert to."

  3. You're using an anonymous method without a parameter list at all which can be converted to any delegate type which doesn't use out/ref parameters. If you tried delegate() { ... } (i.e. an explicitly empty parameter list) then it wouldn't work. This "I don't care about parameters" ability of anonymous methods is the only feature they have which lambda expressions don't.

It's easiest to demonstrate all of this in the context of simple assignments, 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"); };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文