多播委托总是执行最后一个操作

发布于 2024-11-28 04:39:06 字数 894 浏览 0 评论 0原文

所以我有以下代码:

namespace ConsoleApplication1
{
    public delegate int Transformer(int x);

    class Test
    {
        public static void Transform(int[] values, Transformer t)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = t(values[i]);
            }
        }

       static int Square(int x)
        {
            return x * x;
        }

        static int Minus(int x)
       {
           return x - 1;
       }

        static void Main()
        {
            int[] values = { 1, 2, 3 };
            Transformer t = Test.Minus;
            t += Test.Square;

            Test.Transform(values, t);

            foreach (int i in values)
            {
                Console.Write(i + " ");
            }
        }
    }
}

为什么它总是只对数组执行最后一个操作(在我的例子中是 Square )。我应该改变什么才能同时实现 Minus 和 Square ?

So I have the following the code:

namespace ConsoleApplication1
{
    public delegate int Transformer(int x);

    class Test
    {
        public static void Transform(int[] values, Transformer t)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = t(values[i]);
            }
        }

       static int Square(int x)
        {
            return x * x;
        }

        static int Minus(int x)
       {
           return x - 1;
       }

        static void Main()
        {
            int[] values = { 1, 2, 3 };
            Transformer t = Test.Minus;
            t += Test.Square;

            Test.Transform(values, t);

            foreach (int i in values)
            {
                Console.Write(i + " ");
            }
        }
    }
}

Why is it always does only the last operation to the array(Square in my case). What should I need to change so it will do both Minus and Square ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长发绾君心 2024-12-05 04:39:06

多播委托始终返回链中最后一个委托的值。由于您不修改 Test.Minus 和 Test.Square 中的值,而是返回新值,因此仅应用后者。解决这个问题最简单的方法是让你的变压器通过引用获取值并修改它们。例如:


namespace ConsoleApplication1
{
    public delegate void Transformer(ref int x);

    class Test
    {
        public static void Transform(int[] values, Transformer t)
        {
            for (int i = 0; i < values.Length; i++)
            {
                t(ref values[i]);
            }
        }

       static void Square(ref int x)
       {
           x = x * x;
       }

       static void Minus(ref int x)
       {
           x = x - 1;
       }

        static void Main()
        {
            int[] values = { 1, 2, 3 };
            Transformer t = Test.Minus;
            t += Test.Square;

            Test.Transform(values, t);

            foreach (int i in values)
            {
                Console.Write(i + " ");
            }
        }
    }
}

Multicast delegates always return the value of the last delegate in chain. Since you don't modify values in Test.Minus and Test.Square, but return new values, only latter is applied. The simplest way to fix this would to make your transformers take values by reference and modify them. e.g:


namespace ConsoleApplication1
{
    public delegate void Transformer(ref int x);

    class Test
    {
        public static void Transform(int[] values, Transformer t)
        {
            for (int i = 0; i < values.Length; i++)
            {
                t(ref values[i]);
            }
        }

       static void Square(ref int x)
       {
           x = x * x;
       }

       static void Minus(ref int x)
       {
           x = x - 1;
       }

        static void Main()
        {
            int[] values = { 1, 2, 3 };
            Transformer t = Test.Minus;
            t += Test.Square;

            Test.Transform(values, t);

            foreach (int i in values)
            {
                Console.Write(i + " ");
            }
        }
    }
}

晨敛清荷 2024-12-05 04:39:06

因为结果并未链接到所有委托,

所以代码就相当于

 Minus(1);
 return Square(1);

更改代码以更改变量。

 public delegate void Transformer(ref int x);

    public static void Transform(int[] values, Transformer t)
    {
        for (int i = 0; i < values.Length; i++)
        {
            t(ref values[i]);
        }
    }

   static void Square(ref int x)
    {
        x*= x;
    }

    static void Minus(ref int x)
   {
       x--;
   }

更好的解决方案是使用 linq 聚合,因为您可以在不影响源的情况下转换解决方案。

public static int[] Transform(int[] values, params Func<int,int>[] t){
  return values.Select(v=>t.Aggregate(v,(x,f)=>f(x))).ToArray();
}

然后你可以只调用

values=Transform(values,new[] { Minus,Square });

int[] values = {1,2,3};
int[] result = Transform(values,Minus,Square);

在此调用值之后!=结果,因此源不变

Because the result is not chained through all the delegates

the code becomes the equivalent of

 Minus(1);
 return Square(1);

change the code to alter the variable in place.

 public delegate void Transformer(ref int x);

    public static void Transform(int[] values, Transformer t)
    {
        for (int i = 0; i < values.Length; i++)
        {
            t(ref values[i]);
        }
    }

   static void Square(ref int x)
    {
        x*= x;
    }

    static void Minus(ref int x)
   {
       x--;
   }

A far better solution would be to use a linq agregate because you could transform the solution without affecting the source.

public static int[] Transform(int[] values, params Func<int,int>[] t){
  return values.Select(v=>t.Aggregate(v,(x,f)=>f(x))).ToArray();
}

Then you can just call

values=Transform(values,new[] { Minus,Square });

or

int[] values = {1,2,3};
int[] result = Transform(values,Minus,Square);

After this call values!=result so source is unchanged

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文