MethodInvoker的这两种用法之间的区别



MethodInvoke:的这两种用法之间到底有什么区别

1:

textBox1.Invoke(new MethodInvoker(b));

2:

textBox1.Invoke((MethodInvoker)delegate { b(); });

我只知道,如果我愿意,变体2允许我用参数调用b()。但是这两个版本之间有什么区别?

版本1对我来说很清楚:我创建了一个新的委托,并将我的b()方法传递给它,该方法与MethodInvoker委托具有相同的返回类型和参数。委托的标准案例。

但是版本2到底是什么呢?这里的"delegate"关键字是什么意思?

我只知道,如果我愿意,变体2允许我用参数调用b()。

不,即使是第一个版本,你也可以做到:

textBox1.Invoke(new MethodInvoker(b), parameter1, parameter2);

但是这两个版本之间有什么区别?

在第二个版本中,需要调用一个额外的委托(它的主体只是调用b())。可能有这样的用例(例如,如果您需要闭包,请稍后参阅),但在这种情况下,它没有任何意义。

但是版本2到底是什么呢?这里的"delegate"关键字是什么意思?

这是一个匿名方法,如果你检查生成的代码,你会发现它在某种程度上等同于这个:

void MyAnonymousMethod() {
    b();
}
void b() {
}
...
textBox1.Invoke(new MethodInvoker(MyAnonymousMethod));

正如您所看到的,它非常无用(在本例中),因为您添加了一个无用的扩展委托调用。如果您使用它来捕获变量,它可能会很有用:

int a = CalculateValueA();
textBox1.Invoke((MethodInvoker)delegate {
    b(a / CalculateValueC(), anotherParameter); 
});

注意,这与此非常不同:

int a = CalculateValueA();
textBox1.Invoke(new MethodInvoker(b), a / CalculateValueC());

由于,当函数将被调用并计算表达式时。要了解所有的含义,请参阅MSDN,了解有关C#中闭包的详细信息。手工编写的相同代码要复杂得多(您需要定义类来保存参数/函数调用)。对反编译的代码进行快速检查将使这一点更加清晰。

另一种常见的情况是,当您必须适应e方法原型时。MethodInvoker的情况并非如此,但您可能希望调用一个不包含事件参数(包含objectEventArgs参数)的方法。在这种情况下,你有一些选择:

  • 创建一个具有适当原型的事件处理程序方法,然后简单地调用所需的方法
  • 创建一个匿名委托(就像您所做的或使用lambda)。不要忘记,匿名委托不能简单地与事件处理程序分离

V1创建一个新的MethodInvoker对象,并将其作为参数传递给b方法。MethodInvoker然后"对b做什么"取决于类本身。

在V2中,您创建了一个匿名方法并将其强制转换为MethodInvoker,并且不实例化任何"附加对象",您的委托将"直接"执行。使用Lambdas调用此函数的另一种更短的方法:

textBox1.Invoke(() => b()); // or .Invoke((Action)() => b());

在V1中,您也可以用自己的实现来替换MethodInvoker,例如TryCatchLogInvoker,它不直接执行b,而是将其封装以记录"在b内部"发生的异常。

最新更新