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
精彩评论