解释C#代理调用的语法

3
在这个链接http://c-sharp-programming.blogspot.com/2008/07/cross-thread-operation-not-valid.html的代码中,使用了委托来从工作线程更新文本框的值。
我基本上能看出发生了什么,但是这一行的语法特别:
label1.Invoke(del, new object[] { newText });

我感到困惑。请问有人能解释一下吗?为什么在委托中只有一个参数时,我们要使用新的对象数组语法?

完整代码:

delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(string newText)
{
 if (label1.InvokeRequired)
 {
     // this is worker thread
     updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
     label1.Invoke(del, new object[] { newText });
 }
 else
 {
     // this is UI thread
     label1.Text = newText;
 }
}

这是一个错误,label1.Invoke()不是委托。只需编写label1.Invoke(del, newText); - Hans Passant
他是说label1.Invoke()是一个委托吗?我没有看到那个。另外,很好地指出了由于params,可以使用单个参数而无需显式的object[]。 - payo
4个回答

4

TL;DR:

Control.Invoke会调用您的委托上的DynamicInvoke,该委托需要一个对象数组参数来处理任何委托类型。

//

C#中的关键字delegate类似于指定函数指针类型。您可以使用该类型传递具有特定签名的方法。在您的示例中,签名是一个接受1个参数(字符串)并返回无(void)的方法。方法updateLabelText符合该sig。该行:

updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);

只是一种全文检索的说法:
updateLabelTextDelegate del = updateLabelText;

然后,您可以将现在是指向方法 updateLabelText 的指针的变量 del 传递给 Control.Invoke 方法。

label1.Invoke(del, new object[] { newText });

由于在 Control.Invoke 签名中使用了 params,您甚至不必明确表明它是一个 object[]
label1.Invoke(del, newText);
< p > Invoke 方法接受一个对象数组作为参数,它将使用这些参数作为委托的参数。(是的,您的更新方法需要一个字符串参数,请继续阅读) 使用变量del,您可以自己调用updateLabelText

del(newText);

这基本上与以下内容相同:

updateLabelText(newText);

Control.Invoke中,他们调用了您的del方法,但由于委托上的一些辅助方法,它不必知道需要多少参数。您会发现类似这样的内容: 编辑 我进行了深入的研究,内部的调用更像是:
del.DynamicInvoke(args);

其中args是一个object[]。有关您可以使用委托变量(类型为Delegate)执行的操作的更多信息,请在此处阅读更多内容。


3
如果您查看 Control.Invoke 的方法签名,您会看到它使用了 params Object[] args。您可以传递 object[] args 或单个参数。

2
对象数组被传递给委托的 Invoke 方法。在这种情况下,updateLabelTextDelegate 接受一个 string 参数,因此数组中只有一个元素。
实际上,不需要显式创建该数组,而是可以直接将参数作为参数列表传递。
label1.Invoke(del, newText)

也是有效的。


+1 是因为没有使用 new object[],但我要指出这只是由于 params 的存在才成为可能的选项。 - payo

1
首先,值得注意的是这不是在委托上调用Invoke,而是在控件上调用Invoke。现在,如果您查看此处使用的{{link1:Control.Invoke}}的签名,它是这样的:
public Object Invoke(
    Delegate method,
    params Object[] args
)

如果该方法只接受一个特定的委托类型,那么它可以接受该委托所需的适当参数类型。在您的情况下,您的委托只接受一个参数,但是假设我们想要传递一个 Action - 使用上述非常通用的方法,我们可以这样做:
control.Invoke(someDelegate, new object[] { "foo", "bar", 10 });

所以答案是object[]的存在是为了提供通用性,因为委托类型也保持通用。这有点像MethodInfo.Invoke - 在编译时不知道有多少参数的情况下,object[]类型的值是允许各种情况的最佳方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接