为一个genericsC#集合中的每个值调用一个函数
我有一个List集合中的整数值的集合。 我想为集合中的每个值调用一个函数,其中一个函数的参数是一个集合值。 没有在foreach循环中做这个…有没有办法用lambda / linqexpression式来实现呢?
像… myList.Where(p => myFunc(p.Value));
?
在此先感谢,-s
LINQ在这里没有帮助,但你可以使用List<T>.ForEach
:
列表<T> .ForEach方法
对List的每个元素执行指定的操作。
例:
myList.ForEach(p => myFunc(p));
传递给lambdaexpression式的值是列表项,所以在本例中,如果myList
是List<long>
则p
是一个long
。
正如其他海报所指出的,您可以使用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( ... );
邑! 你可以使用List.ForEach
但问题是只适用于列表(当然,你可以改变一切,以dynamic列表,但更less的代码更有趣:) )。 除此之外,您必须使用不提供任何返回types的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的集合取代的string数组。
其次 , Select
一个Func<string>
内部Func<string>
将在给定数组的每个元素声明为x
。
( 看看空括号,记住当你定义一个Func<type**1**, type**2**, ..., type**n**>
总是最后一个types是返回types,所以当你写Func<string>
它表示一个没有input参数的函数,它的返回types是string )
很明显,我们希望使用给定数组上的函数(new string[] { "d", "f" })
,这就是为什么我定义一个没有参数的函数,而且我已经使用了相同的variablesx
Func<>
引用相同的数组元素。
第三 ,如果你不把第二个select,那么你有一个返回string的两个函数的集合,而且他们已经从第一个数组得到了他们的input。 你可以做到这一点,并保留在一个anonymous
variables的结果,然后调用他们的.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>();
最后 ,我将结果转换为一个数组! 现在你有一个string数组!
对不起,它会变长! 我希望这会有用。
您可以使用List.ForEach方法,如下所示:
myList.ForEach(p => myFunc(p));
否 – 如果要为列表中的每个项目调用函数,则必须调用列表中每个项目的函数。
但是,可以使用IList<T>.ForEach()
方法作为一些语法糖来使代码的“业务结束”更具可读性,如下所示:
items.ForEach(item => DoSomething(item));
如果你不想使用L ist<T>
的ForEach方法,而是使用IEnumerable<T>
(就像“LINQ:ing”时经常这样做),我build议由Jon Skeet等人写的MoreLINQ 。
MoreLINQ会给你ForEach,还有Pipe(以及其他一些方法),它对每个元素执行一个动作,但返回相同的IEnumerable<T>
(与void相比)。
这是一个迷你(但完整)的例子。
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); }