为通用 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 表达式的值是列表项,因此在此示例中,如果 myListList<long>,则 plong

【讨论】:

谢谢——这正是我一直在寻找的东西,可能在某个地方看到过,但不记得了...... 或者,如果 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&lt;&gt; 预测。

无论如何,您想要的答案都有,您可以用Func&lt;&gt; 猜测的相同方式使其成为可能,但有一个小技巧如下:

我会在这里做所有事情:

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&lt;string&gt;,因为它称为x。。 p>

(看看空括号,记住当你定义一个Func&lt;type**1**, type**2**, ..., type**n**&gt;时,最后一个类型总是返回类型,所以当你只写Func&lt;string&gt;时,它表示一个没有输入参数的函数及其返回类型是字符串)

很明显,我们想在给定数组(new string[] "d", "f" ) 上使用函数,这就是为什么我定义了一个没有参数的函数,而且我在Func&lt;&gt; 内部使用了相同的变量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&lt;T&gt;.ToList&lt;T&gt; 返回一个 IList&lt;T&gt;【参考方案4】:

您可以使用 List.ForEach 方法,如下所示:

myList.ForEach(p => myFunc(p));

【讨论】:

【参考方案5】:

否 - 如果您想为列表中的每个项目调用一个函数,您必须为列表中的每个项目调用该函数。

但是,您可以将IList&lt;T&gt;.ForEach() 方法用作一点语法糖,以使代码的“业务端”更具可读性,如下所示:

items.ForEach(item => DoSomething(item));

【讨论】:

【参考方案6】:

您可以使用 ForEach 方法:

MSDN:

http://msdn.microsoft.com/en-us/library/bwabdf9z.aspx

【讨论】:

【参考方案7】:

如果你不想使用List&lt;T&gt; 的ForEach 方法,而是使用IEnumerable&lt;T&gt;(就像“LINQ:ing”时经常使用的那样),我建议使用Jon Skeet 编写的MoreLINQ,等。

MoreLINQ 将为您提供 ForEach 和 Pipe(以及许多其他方法),它们对每个元素执行一个操作,但返回相同的 IEnumerable&lt;T&gt;(与 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# 集合中的每个值调用一个函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

表达式树练习实践:C#值类型引用类型泛型集合调用函数

多映射通用集合类(C#实现)--支持一键多值存储

将 32 个布尔值的集合转换为 32 位整数 [重复]

C#中foreach用法

C# 主窗口调用子窗口的值传递?

将枚举值作为参数的通用 C# 方法[重复]