【问题标题】:c# delegate not working as it should?c#委托不能正常工作?
【发布时间】:2012-04-06 22:41:15
【问题描述】:

我对 c# 有点陌生,所以我想出了这个问题。问题:为什么调用func2? 哦,还有一件事。假设我向委托添加了一个函数。在这个函数中,我调用了另一个委托,但是我想确保在这个函数调用这个委托之前调用添加到第一个委托的所有其他函数,是否有任何干净的解决方案(对 getInvocationList 并不真正感兴趣)。 谢谢各位,你们是最棒的。

class Program
{
    delegate void voidEvent();
    voidEvent test;

    private void func1()
    {
        Console.Write("func1");
        test -= func2;
    }

    private void func2()
    {
        Console.WriteLine("func2");
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        p.test += p.func1;
        p.test += p.func2;
        p.test();
    }
}

【问题讨论】:

    标签: c# delegates


    【解决方案1】:

    每次更改委托(+= 或 -=)时,您实际上是在创建调用列表的完整副本(将被调用的方法)。

    因此,当您调用p.test(); 时,您将在那个时间点调用调用列表中的每个委托。在其中一个处理程序中更改 this 将为下一次调用更改它,但不会更改当前正在执行的调用。

    【讨论】:

    • +1。是的。这就是为什么您可以在多线程场景中编写var func = p.test; if (func != null) { func(); } 而无需锁定任何东西的原因。因为funcp.test 的副本,并不关心对p.test 所做的更改。
    • 但在我调用 test-= func2 并调用 getinvocationlist 后,我​​可以看到 func2 不再出现在列表中。所以你是说每个委托都有两个列表,一个当前正在调用(并且不可访问),另一个将在下次调用?
    • @user1316459,它实际上并没有两个列表。但是当你从一个文件中调用一个委托时,你实际上是在说:“获取字段的值立即然后调用它”。这意味着您调用的是test 值的副本,而不是test 本身。
    【解决方案2】:

    里德当然是正确的。这是另一种思考方式。

    class Number
    {
        public static Number test;
        private int x;
        public Number(int x) { this.x = x; }
        public Number AddOne() 
        {
            return new Number(x + 1);
        }
        public void DoIt()
        {
            Console.WriteLine(x);
            test = test.AddOne();
            Console.WriteLine(x);
        }
        public static void Main()
        {
            test = new Number(1);
            test.DoIt(); 
        }
    }
    

    应该打印 1、1 还是 1、2?为什么?

    它应该打印 1, 1。当你说

    test.DoIt();
    

    这并不意味着

            Console.WriteLine(test.x);
            test = test.AddOne();
            Console.WriteLine(test.x);
    

    !相反,这意味着

    Number temporary = test;
    Console.WriteLine(temporary.x);
    test = test.AddOne();
    Console.WriteLine(temporary.x);
    

    改变test的值不会改变DoIt中this的值

    你正在做同样的事情。更改 test 的值不会更改您正在调用的函数列表;您要求调用特定的函数列表,该列表将被调用。你不能在中途改变它,就像你不能在方法调用中途改变this的含义一样。

    【讨论】:

    • 您的Number 定义中似乎缺少x 字段。
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 1970-01-01
    相关资源
    最近更新 更多