C#委托实例化

时间:2012-10-18 09:37:08

标签: delegates

class Program
{
    delegate void StringProcessor(string input);

    class Person
    {
        string name;

        public Person(string name) { this.name = name; }

        public void Say(string message)
        {
            Console.WriteLine("{0} says: {1}", name, message);
        }
    }

    class Background
    {
        public static void Note(string note)
        {
            Console.WriteLine("({0})", note);
        }
    }

    static void Main(string[] args)
    {
        Person jon = new Person("Jon");
        Person tom = new Person("Tom");

        StringProcessor jonsVoice, tomsVoice, background;

        jonsVoice = new StringProcessor(jon.Say);
        tomsVoice = new StringProcessor(tom.Say);
        background = new StringProcessor(Background.Note);

        StringProcessor p = new StringProcessor(jonsVoice);
        p += tomsVoice;
        p -= jonsVoice;
        p("Hello");

    }
}

此程序打印

Jon says: Hello
Tom says: Hello

而不是

Tom says: Hello

此删除不起作用:p -= jonsVoice;

但为什么?

您能否澄清一下这个问题,或者获取一些有关委托实例化的有用链接与另一位代表。我对卧底信息感兴趣。

1 个答案:

答案 0 :(得分:0)

A delegate is an object which represents a method and, optionally, the "this" object associated with that method.

使用+ =运算符组合委托时,结果为Multicast Delegate,表示要调用的委托列表。 (事实上​​,所有代表都是多播代理,创建一个这样的代理:

jonsVoice = new StringProcessor(jon.Say);

导致多播委托在其InvocationList中具有单个委托。)

您可以使用 - =运算符从Invocation列表中删除委托。

那么为什么上面的例子不起作用?因为在p。

的调用列表中没有与jonsVoice匹配的委托

p有一个由两个委托组成的调用列表:

  • 一个指向tomObject的Say方法
  • 一个指向StringProcessor对象的Invoke方法

这是因为你通过将StringProcessor构造函数传递给另一个StringProcessor来初始化p:

jonsVoice = new StringProcessor(jon.Say);
...
StringProcessor p = new StringProcessor(jonsVoice);

导致指向另一个StringProcessor委托的StringProcessor委托。

您可以通过调用该委托上的GetInvocationList方法来检查委托的调用列表。这将按照调用它们的顺序返回一组委托。

StringProcessor p = new StringProcessor(jonsVoice);
p += tomsVoice;
p -= jonsVoice;

foreach (var delegateItem in p.GetInvocationList())
{
    Console.WriteLine("Delegate of {0}.{1}", delegateItem.Target.GetType().Name, delegateItem.Method.Name);
}

结果是:

Delegate of StringProcessor.Invoke
Delegate of Person.Say

当你调用p - = jonsVoice时,调用列表不包含指向jon对象的Person.Say方法的委托(就像jonsVoice那样),所以没有什么可以删除。

如果你这样初始化p:     StringProcessor p = jonsVoice;

你应该得到你期望的结果。