委托问题

3

我刚学习C#,有两个关于delegate的问题。

MSDN显示Delegate类只有两个构造函数,每个都接受两个参数。然而,在下面的程序中,我使用了一个看似只有一个参数的构造函数来实例化Delegate对象(请参见被注释的行)。

using System;

static class Program
{
    public delegate void MyDelegate();

    static void MyMethod()
    {
        Console.WriteLine("I'm inside MyMethod!");
    }

    static void Main()
    {
        MyDelegate myDelegate = new MyDelegate(MyMethod); // Constructor Call
        myDelegate();
    }
}

我有个疑问:我是否理解错了什么?

我的第二个问题是:在声明一个或多个参数的delegate时,为什么需要给参数命名?在C++中,我们可以在类内部做出这样的声明:

public delegate void MyOtherDelegate(int, int, string);

3
如果你有两个问题,请分别提出,否则你可能会陷入这样一种情况:有些人回答其中一个问题,而有些人回答另一个问题,那么哪一个回答会被选定作为答案呢?这会变得很混乱。请每个问题只问一个问题,避免出现这种情况。 - Eric Lippert
一位语言设计师非常清楚歧义的复杂性 :) @EricLippert - nawfal
2个回答

2

看起来你在调用一个标准构造函数,但是C#编译器实际上在你的代码中进行了一些微妙的处理。当你写下:

MyDelegate myDelegate = new MyDelegate(MyMethod);

您实际上并没有直接调用MSDN上列出的任何构造函数。它会调用编译器自动定义的委托类型MyDelegate上的构造函数(这些构造函数未在MSDN上显示)。事实上,甚至不能直接调用在MSDN上列出的构造函数:

此构造函数不能在应用程序代码中使用。要通过指定实例方法的名称创建委托,请使用CreateDelegate方法的重载...

值得注意的是,您甚至可以为了简洁而这样做:
MyDelegate myDelegate = MyMethod;

为什么需要参数名称,也许对于一般的编译来说它们并不是严格必需的,但我认为CLR的设计者想要与运行时的其他功能保持一致。它允许您做一些您无法以其他方式完成的事情,比如指定显式参数名称:

Func<int, int> foo = x => x + 1;
foo(arg: 1);

这也意味着您可以通过反射检查参数名称,并有可能对其进行一些有用的处理。


1

并没有完全回答你的问题,但需要注意的是,C#也支持Func委托。在这种情况下,您甚至不需要声明任何内容。

例如,此方法接受一个具有字符串类型参数和Int输出的委托。

public static void DoSomethingWithDelegate(Func<string, Int32> converstionDelegate)
{
    int x = converstionDelegate("1");
}

在这里阅读更多相关内容:http://msdn.microsoft.com/en-us/library/bb549151.aspx


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