为通用 c# 集合中的每个值调用一个函数[重复]
Posted
技术标签:
【中文标题】为通用 c# 集合中的每个值调用一个函数[重复]【英文标题】:call a function for each value in a generic c# collection [duplicate] 【发布时间】:2010-12-25 10:20:00 【问题描述】:我在 List 集合中有一组整数值。 我想为集合中的每个值调用一个函数,其中函数的参数之一是集合值。 如果不在 foreach 循环中执行此操作...有没有办法使用 lambda/linq 表达式来完成此操作?
类似... myList.Where(p => myFunc(p.Value));
?
提前致谢, -s
【问题讨论】:
你需要函数产生的值还是运行函数的副作用? 您拒绝 foreach 循环解决方案有什么原因吗?我说一个声明应该有副作用。如果您想对序列的每个成员调用副作用函数,那么专门设计用于执行此操作的语句——foreach 语句——似乎是自然的选择。你能解释一下为什么你拒绝为你想要的而设计的语言功能吗? @Eric 没错,我正要发布那个。我一直不明白为什么有人会使用List<T>.ForEach
而不是foreach。善用 Linq 可以混淆很多复杂的、嵌套的代码;但是,有时人们似乎喜欢 lambda 表达式的外观。
【参考方案1】:
LINQ 在这里没有帮助,但你可以使用 List<T>.ForEach
:
List
.ForEach 方法 对列表的每个元素执行指定的操作。
例子:
myList.ForEach(p => myFunc(p));
传递给 lambda 表达式的值是列表项,因此在此示例中,如果 myList
是 List<long>
,则 p
是 long
。
【讨论】:
谢谢——这正是我一直在寻找的东西,可能在某个地方看到过,但不记得了...... 或者,如果 myFunc 与预期的 ForEach 委托的签名匹配,您可以指定myList.ForEach(myFunc)
。【参考方案2】:
正如其他海报所指出的,您可以使用List<T>.ForEach
。
但是,您可以轻松编写一个扩展方法,允许您在任何 IEnumerable<T>
上使用 ForEach
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
foreach(T item in source)
action(item);
这意味着你现在可以这样做:
myList.Where( ... ).ForEach( ... );
【讨论】:
【参考方案3】:耶!您可以使用List.ForEach
,但问题是它仅适用于列表(当然您可以随时将所有内容更改为列表,但更少的代码更有趣:))。此外,您必须使用不提供任何返回类型的Action<>
预测。
无论如何,您想要的答案都有,您可以用Func<>
猜测的相同方式使其成为可能,但有一个小技巧如下:
我会在这里做所有事情:
string[] items = (new string[] "d", "f" ).
Select(x => new Func<string>(() =>
//Do something here...
Console.WriteLine(x);
return x.ToUpper();
)).Select(t => t.Invoke()).ToArray<string>();
这里有几点:
首先,我已经动态定义了一个字符串数组,它可以被任何支持 LINQ 的集合替换。
第二,在Select
内部,将为给定数组的每个元素声明一个Func<string>
,因为它称为x
。。 p>
(看看空括号,记住当你定义一个Func<type**1**, type**2**, ..., type**n**>
时,最后一个类型总是返回类型,所以当你只写Func<string>
时,它表示一个没有输入参数的函数及其返回类型是字符串)
很明显,我们想在给定数组(new string[] "d", "f" )
上使用函数,这就是为什么我定义了一个没有参数的函数,而且我在Func<>
内部使用了相同的变量x
来引用相同的数组元素。
第三,如果您不放置 second Select,那么您将拥有两个返回字符串的函数的集合,并且它们已经从第一个数组。您可以这样做并将结果保存在anonymous
变量中,然后调用他们的.Invoke
方法。我写在这里:
var functions = (new string[] "d", "f" ).
Select(x => new Func<string>(() =>
//Do something here...
Console.WriteLine(x);
return x.ToUpper();
));
string[] items = functions.Select(t => t.Invoke()).ToArray<string>();
最后,我将结果转换为数组!现在你有了一个字符串数组!
对不起,它变长了!!希望对你有用。
【讨论】:
既然我们已经在使用 linq,为什么不在.ForEach()
前面加上 .ToList()
呢? IEnumerable<T>.ToList<T>
返回一个 IList<T>
。【参考方案4】:
您可以使用 List.ForEach 方法,如下所示:
myList.ForEach(p => myFunc(p));
【讨论】:
【参考方案5】:否 - 如果您想为列表中的每个项目调用一个函数,您必须为列表中的每个项目调用该函数。
但是,您可以将IList<T>.ForEach()
方法用作一点语法糖,以使代码的“业务端”更具可读性,如下所示:
items.ForEach(item => DoSomething(item));
【讨论】:
【参考方案6】:您可以使用 ForEach 方法:
MSDN:
http://msdn.microsoft.com/en-us/library/bwabdf9z.aspx
【讨论】:
【参考方案7】:如果你不想使用List<T>
的ForEach 方法,而是使用IEnumerable<T>
(就像“LINQ:ing”时经常使用的那样),我建议使用Jon Skeet 编写的MoreLINQ,等。
MoreLINQ 将为您提供 ForEach 和 Pipe(以及许多其他方法),它们对每个元素执行一个操作,但返回相同的 IEnumerable<T>
(与 void 相比)。
【讨论】:
【参考方案8】:这是一个迷你(但完整的)示例。
public class Employee
public string EmployeeNumber get; set;
public DateTime? HireDate get; set;
public class EmployeeCollection : List<Employee>
private void RunTest()
EmployeeCollection empcoll = new EmployeeCollection();
empcoll.Add(new Employee() EmployeeNumber = "1111", HireDate = DateTime.Now );
empcoll.Add(new Employee() EmployeeNumber = "3333", HireDate = DateTime.Now );
empcoll.Add(new Employee() EmployeeNumber = "2222", HireDate = null );
empcoll.Add(new Employee() EmployeeNumber = "4444", HireDate = null );
//Here's the "money" line!
empcoll.Where(x => x.HireDate.HasValue == false).ToList().ForEach(item => ReportEmployeeWithMissingHireDate(item.EmployeeNumber));
private void ReportEmployeeWithMissingHireDate(string employeeNumber)
Console.WriteLine("We need to find a HireDate for '0'!", employeeNumber);
【讨论】:
以上是关于为通用 c# 集合中的每个值调用一个函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章