开发者

Multicast delegate always does the last operation

开发者 https://www.devze.com 2023-03-25 03:18 出处:网络
So I have the following the code: namespace ConsoleApplication1 { public delegate int Transformer(int x);

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 ?


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 + " ");
            }
        }
    }
}


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号