我试过这段代码:
Func<int, int> f3 = (int x) => x * 3;
f3 += (int x) => x * 4;
Console.WriteLine(f3(5));
我希望输出结果为:
15个
20个
但我只有20岁。
答案 0 :(得分:2)
首先,+=
只是这个上下文中的一个语法糖,所以让我们重写代码以显示显式方法调用:
Func<int, int> f3 = x => x * 3;
f3 = (Func<int, int>)Delegate.Combine(f3, (Func<int, int>)(x => x * 4));
Console.WriteLine(f3.Invoke(5));
为什么只打印一个值而不是两个值有四个原因:
f3
是Func<int, int>
,意味着它有一个int
参数并返回int
。您拨打f3
一次,这样您就只能获得一个int
。
Delegate.Combine创建一个新的多播委托,其中包含所组合参数的调用列表,然后将其存储到f3
。调用委托会调用其调用列表中的所有函数,并且它会发生,以便只从整个调用返回列表中最后一个函数返回的值。
您在单个值(int
)上调用 WriteLine ,因此只打印一个整数。
从方法调用中返回多个值的最接近的方法是使用元组。 .NET中的方法本身不能返回多个值。
如果您尝试使用 Delegate.Combine (+=
)期望能够从调用列表中访问所有返回的值,那么您使用的是错误的方法。 System.MulticastDelegate 不适合此类调用。
有很多方法可以解决这个问题。一个是使用函数列表(或带有函数列表的自定义类)并单独调用它们。
另一种方法是访问调用列表中的所有委托并手动调用它们:
public static object[] AggregateInvoke(this Delegate del, params object[] args)
{
Delegate[] invlist = del.GetInvocationList();
object[] results = new object[invlist.Length];
for(int i = 0; i < invlist.Length; i++)
{
results[i] = invlist[i].DynamicInvoke(args);
}
return results;
}
public static TRet[] AggregateInvoke<TArg,TRet>(this Func<TArg, TRet> del, TArg arg)
{
Delegate[] invlist = del.GetInvocationList();
TRet[] results = new TRet[invlist.Length];
for(int i = 0; i < invlist.Length; i++)
{
results[i] = ((Func<TArg, TRet>)invlist[i]).Invoke(arg);
}
return results;
}
第一种方法适用于所有代理,第二种方法仅适用于您的示例中的单参数函数。我不建议使用此而不是普通的调用,因为它不是通常调用委托的方式。我建议使用第一种方法。
答案 1 :(得分:-1)
您可以使用元组(.Net 4.0)从函数返回多个值。
static void Main() {
// Create three-item tuple.
Tuple<int, string, bool> tuple = new Tuple<int, string, bool>(1, "cat", true);
// Access tuple properties.
if (tuple.Item1 == 1) { Console.WriteLine(tuple.Item1); }
if (tuple.Item2 == "dog") { Console.WriteLine(tuple.Item2); }
if (tuple.Item3) { Console.WriteLine(tuple.Item3); }
}
这是你可以从函数中返回元组对象的方法。
public Tuple<T1,String> Create<T1>(T1 item1) {
return new Tuple<T1>(item1,"string");
}
答案 2 :(得分:-1)
你可以说是,函数可以通过Tuple(和ValueTuple)或IEnumerable等返回多个值。
但是在你的例子中你想要相反:在一个值上运行一些函数。
将新函数放在同一个变量中,第一个函数将被运行。同样在+ =中,仅在最后一个函数中返回返回值。
我怎么看:
var listFunctions = new List<System.Func<int, int>>();
listFunctions.Add(x => x * 3);
listFunctions.Add(x => x * 4);
listFunctions.ForEach(x => Console.WriteLine( x(5)));