delegate void DelegateTest();
DelegateTest delTest;
调用delTest.Invoke()
与delTest()
有什么区别?两者都会在当前线程上执行委托,对吗?
delTest()
表单是编译器助手,其实它是对 Invoke()
的调用。
Richard的回答是正确的,不过从C# 6.0开始,使用Invoke()
直接调用可以在使用空值条件运算符时具有优势。根据微软文档:
另一个使用空值条件成员访问的情况是通过更少的代码以线程安全的方式调用委托。旧的方法需要如下所示的代码:
var handler = this.PropertyChanged; if (handler != null) handler(…);
新方式更简单:
PropertyChanged?.Invoke(…)
新的方式是线程安全的,因为编译器生成的代码只评估了一次PropertyChanged并将结果保存在临时变量中。您需要显式调用Invoke方法,因为没有空引用委托调用语法PropertyChanged?(e)。
没错,两者的结果完全相同。
当然,前提是您已经正确初始化了delTest
。
delTest
为null
,两种语法再次导致相同的结果(在那种情况下是从尝试调用的行抛出一个NullReferenceException
)。 - Jeppe Stig NielsenDelegate.Invoke和Delegate()是相同的。它们都执行相同的操作。请参见下面的代码:
static async Task Main(string[] args)
{
MyDelegate mydelegate = new MyDelegate(CallMe);
mydelegate.Invoke("Reza");
mydelegate("Reza");
}
public delegate void MyDelegate(string message);
public static void CallMe(string message)
{
}
IL
IL_001a: ldarg.0
IL_001b: ldfld class TestConsole.Program/MyDelegate TestConsole.Program/'<Main>d__1'::'<mydelegate>5__1'
IL_0020: ldstr "Reza"
IL_0025: callvirt instance void TestConsole.Program/MyDelegate::Invoke(string)
IL_002a: nop
IL_002b: ldarg.0
IL_002c: ldfld class TestConsole.Program/MyDelegate TestConsole.Program/'<Main>d__1'::'<mydelegate>5__1'
IL_0031: ldstr "Reza"
IL_0036: callvirt instance void TestConsole.Program/MyDelegate::Invoke(string)
IL_003b: nop
我通常使用Invoke()
,因为你可以使用null-check并且阅读代码的人更容易看出正在使用委托。
null-check
MyDelegate mydelegate = null;
mydelegate?.Invoke("Reza");
mydelegate("Reza"); // Error: System.NullReferenceException
object[]
传递并返回object
。 - Richard