1
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;

但为什么?

您能否澄清这一点或获得一些有关与另一个委托的委托实例化的有用链接。我对卧底信息很感兴趣。

4

1 回答 1

0

委托是一个对象,它代表一个方法,并且可以选择与该方法关联的“this”对象。

当您使用 += 运算符组合委托时,结果是表示要调用的委托列表的多播委托。(实际上所有的委托都是多播委托,创建一个像这样的委托:

jonsVoice = new StringProcessor(jon.Say);

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

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

那么为什么你上面的例子没有工作呢?因为 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;

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

于 2013-04-12T19:59:08.467 回答