调用方法(委托)和直接调用有何区别?

37

也许这个问题已经被问过了,我通过谷歌搜索但是没有找到答案。

代理原型

delegate void method1(string str);

添加回调方法

method1 objDel2;           
objDel2 = new method1(TestMethod1);            
objDel2("test");
objDel2.Invoke("Invoke");

在上面的代码中,objDel2("test");objDel2.Invoke("Invoke"); 进行了相同的任务。哪一个更好,还是两个都一样。


1
你是在问 bjDel2("test");objDel2.Invoke("Invoke"); 是否相同吗?是的,它们是相同的。还是你在问哪一个应该被优先选择?这主要取决于个人意见。 - dtb
它们是一样的,区别只在于显式地调用invoke。 - Rohit
1个回答

61

它们是完全相同的——这只是编译器的纯语法糖(见下文)。至于哪个更受欢迎:两者都可以/都不可以。

static class Program {

    static void Main()
    {
        method1 objDel2;
        objDel2 = new method1(TestMethod1);
        objDel2("test");
        objDel2.Invoke("Invoke");
    }
    delegate void method1(string val);
    static void TestMethod1(string val) {
        System.Console.WriteLine(val);
    }
}

有IL

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] class Program/method1 'method')
    L_0000: ldnull 
    L_0001: ldftn void Program::TestMethod1(string)
    L_0007: newobj instance void Program/method1::.ctor(object, native int)
    L_000c: stloc.0 
    L_000d: ldloc.0 
    L_000e: ldstr "test"
    L_0013: callvirt instance void Program/method1::Invoke(string) ***HERE***
    L_0018: ldloc.0 
    L_0019: ldstr "Invoke"
    L_001e: callvirt instance void Program/method1::Invoke(string) ***HERE***
    L_0023: ret 
}

请注意它们都执行相同的操作(请参见我标记为***HERE***的两个位置)。


39
在C#6中,使用Invoke的优点是可以利用空值传播运算符避免必要的空值检查:objDel2?.Invoke("Invoke");。你无法编写objDel2?("test"); - Tim Schmelter
1
@TimSchmelter 是的,它非常棒,可以在不必执行“快照、测试、调用”三重操作的情况下触发事件。 - Marc Gravell
@MarcGravell,您从哪里获取IL代码?是否有任何可用的工具? - RGS
2
@RGD “ildasm” 在 Visual Studio 或 .NET SDK 中作为默认安装。还有像 .NET Reflector 这样的工具,但那不是免费的。通常使用“ildasm”就足够了。 - Marc Gravell
4
@RGS https://sharplab.io/ 在查看代码片段的中间语言(IL)时也非常有用。 - Menyus

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