Func return 可以在 C# 中使用多个值吗?
Can Func return multiple values in C#?
我试过这段代码:
Func<int, int> f3 = (int x) => x * 3;
f3 += (int x) => x * 4;
Console.WriteLine(f3(5));
我希望输出是:
15
20
但是我只得到20.
您可以使用元组(.Net 4.0) return 函数中的多个值。
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); }
}
这就是您可以 return 从函数中获取元组对象的方法。
public Tuple<T1,String> Create<T1>(T1 item1) {
return new Tuple<T1>(item1,"string");
}
你可以说是的,函数可以 return 多值,通过 Tuple(和 ValueTuple)或 IEnumerable 等。
但在您的示例中,您想要相反的结果:运行 某些函数基于一个值。
将新函数放在同一变量中的位置,第一个函数已 运行 结束。同样在 += 中,仅从最后一个函数多播 return-值 return。
我怎么看:
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)));
首先,+=
在这个上下文中只是一个语法糖,所以让我们重写代码以显示显式方法调用:
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
参数并且 return 是一个 int
。你调用 f3
一次,所以你只会得到一个 int
.
Delegate.Combine 创建一个新的多播委托,其中结合了参数的调用列表,然后将其存储到 f3
。调用委托会调用其调用列表中的所有函数,并且发生这种情况,因此整个调用中只有列表中最后一个函数的 returned 值是 returned 值。
您正在对单个值 (int
) 调用 WriteLine,因此只打印一个整数。
最接近从方法调用中 returning 多个值的方法是使用元组。 .NET 中的方法本身不能 return 多个值。
如果您尝试使用 Delegate.Combine (+=
),希望能够从调用中访问所有 returned 值列表,您使用了错误的方法。 System.MulticastDelegate 不适合这种调用。
有很多方法可以解决这个问题。一种是使用函数列表(或带有函数列表的自定义 class)并分别调用它们。
另一种方法是访问调用列表中的所有委托并手动调用它们:
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;
}
第一种方法适用于所有委托,第二种方法仅适用于您的示例中的单参数函数。我不建议使用它来代替普通调用,因为这不是通常调用委托的方式。我建议使用第一种方法。
我试过这段代码:
Func<int, int> f3 = (int x) => x * 3;
f3 += (int x) => x * 4;
Console.WriteLine(f3(5));
我希望输出是:
15
20
但是我只得到20.
您可以使用元组(.Net 4.0) return 函数中的多个值。
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); }
}
这就是您可以 return 从函数中获取元组对象的方法。
public Tuple<T1,String> Create<T1>(T1 item1) {
return new Tuple<T1>(item1,"string");
}
你可以说是的,函数可以 return 多值,通过 Tuple(和 ValueTuple)或 IEnumerable 等。
但在您的示例中,您想要相反的结果:运行 某些函数基于一个值。
将新函数放在同一变量中的位置,第一个函数已 运行 结束。同样在 += 中,仅从最后一个函数多播 return-值 return。
我怎么看:
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)));
首先,+=
在这个上下文中只是一个语法糖,所以让我们重写代码以显示显式方法调用:
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
参数并且 return 是一个int
。你调用f3
一次,所以你只会得到一个int
.Delegate.Combine 创建一个新的多播委托,其中结合了参数的调用列表,然后将其存储到
f3
。调用委托会调用其调用列表中的所有函数,并且发生这种情况,因此整个调用中只有列表中最后一个函数的 returned 值是 returned 值。您正在对单个值 (
int
) 调用 WriteLine,因此只打印一个整数。最接近从方法调用中 returning 多个值的方法是使用元组。 .NET 中的方法本身不能 return 多个值。
如果您尝试使用 Delegate.Combine (+=
),希望能够从调用中访问所有 returned 值列表,您使用了错误的方法。 System.MulticastDelegate 不适合这种调用。
有很多方法可以解决这个问题。一种是使用函数列表(或带有函数列表的自定义 class)并分别调用它们。
另一种方法是访问调用列表中的所有委托并手动调用它们:
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;
}
第一种方法适用于所有委托,第二种方法仅适用于您的示例中的单参数函数。我不建议使用它来代替普通调用,因为这不是通常调用委托的方式。我建议使用第一种方法。