Implicitly convert method group to Delegate (for argument of Control.Invoke)

拟墨画扇 提交于 2019-12-22 04:30:14

问题


I'm working on a Windows Forms application, and it contains custom controls with methods that can potentially be called from threads other than the UI thread. So these methods therefore look a bit like this to prevent exceptions:

public void DoSomeStuff()
{
    if (InvokeRequired)
    {
        Invoke((Action)DoSomeStuff);
    }
    else
    {
        // Actually do some stuff.
    }
}

The explicit cast of the method group DoSomeStuff to an Action caught my attention, and so I've been looking into delegates and other related subjects more deeply than I have before.

Although I've seen some related questions here, I haven't been able to find exactly the answer to mine, which is:

Why does the method group DoSomeStuff require explicit casting to an Action in this case?

If I remove the cast, then I get two errors:

Error 102 Argument 1: cannot convert from 'method group' to 'System.Delegate'

Error 101 The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delegate, params object[])' has some invalid arguments

The fact that the compiler is apparently confused about which overload of Invoke to use seems like a pretty big hint, but I'm still not sure about why exactly it can't figure that out. I would expect the compiler to deduce that the first overload of Invoke, which takes a single Delegate argument, is the one that should be used.

I would expect that because there is no problem if the code is written like this:

Action a = DoSomeStuff;
Invoke(a);

The method group DoSomeStuff can be implicitly converted to the Action delegate type, and Action derives (technically?) from System.Delegate, so Invoke can handle the argument a without any trouble. But then why can't the implicit conversion be done by the compiler when I try to pass DoSomeStuff as the argument directly? To be honest I'm not convinced by my own logic here, but I still am not sure what I'm missing.


回答1:


The problem is not that the compiler has trouble picking an overload. The "best match" overload is the one you want but it has invalid arguments. The C# language does not define any implicit conversion from method group (DoSomeStuff) to System.Delegate.

You might say that the compiler should just pick one of the Action/Func types and this has been requested as a language feature. Right now this is not part of C#. (I don't know why; I hope the language request goes through.)

System.Windows.Forms.Control.Invoke was created in .NET 1.0. Today, one would use the following signatures:

void Invoke(Action action);
Task InvokeAsync(Action action);

And it would simply work.

Try to make the migration to await and this stops being a concern.



来源:https://stackoverflow.com/questions/31473865/implicitly-convert-method-group-to-delegate-for-argument-of-control-invoke

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!