所以我有以下代码:
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?
答案 0 :(得分:4)
多播代理始终返回链中最后一个委托的值。由于您不修改Test.Minus和Test.Square中的值,但返回新值,因此仅应用后者。解决此问题的最简单方法是使变换器通过引用获取值并进行修改。 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 + " ");
}
}
}
}
答案 1 :(得分:3)
因为结果没有通过所有代理链接
代码相当于
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 agregate,因为您可以在不影响源的情况下转换解决方案。
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);
此调用值后!=结果因此源未更改