有没有像Forist for IList的方法?

Joe*_*ang 42 c#

可能重复:
LINQ等效于IEnumerable <T>的foreach

List<T>有一个调用的方法ForEach,它对每个元素执行传递的操作.

var names = new List<String>{ "Bruce", "Alfred", "Tim", "Richard" };

names.ForEach(p =>  { Console.WriteLine(p); });
Run Code Online (Sandbox Code Playgroud)

但是,如果names不是一个List<T>但是IList<T>,IList<T>没有像这样的方法ForEach.还有其他选择吗?

O. *_*per 42

使用foreach循环:

foreach (var p in names) {
    Console.WriteLine(p);
}
Run Code Online (Sandbox Code Playgroud)

如果这实际上没有提高可读性,则没有理由在整个地方使用委托和扩展方法; 一个foreach循环并没有明确地告诉读者正在做什么而不是一个ForEach方法.

  • @nawfal我非常赞同帖子的最后一行; `.ForEach`方法在很大程度上是超级的; 它也不那么直接.在大多数</ s>*所有*案例中,只使用常规`foreach`是首选. (7认同)
  • 我不同意最后一行.它使代码更短,更不容易出错.为什么List <T>会有一个Foreach? (3认同)
  • @ORMapper关于这个链接,http://blogs.msdn.com/b/mazhou/archive/2011/09/21/why-no-foreach-method-on-ienumerable-interfaces.aspx ppl经常引用,积分对我来说并不令人信服,就像那个帖子中的许多读者一样. (3认同)
  • List <T> .ForEach实际上并不是一个特别好的设计.一方面它实际上转换为'for'循环而不是ForEach循环(我认为设计师试图获得更多的性能).这意味着你传递给List <T> .ForEach的'action'实际上可以修改列表本身而不会抱怨!这可能是一个令人讨厌的错误来源.... (2认同)
  • @AmitMittal在`List <T>`上有很多修改集合的方法,还有很多不修改的方法(比如linq).关键是你画线的地方. (2认同)

naw*_*fal 21

如果你IList<T>是一个数组(T[]),那么你就有类似于on的Array.ForEach方法.您可以创建自定义的扩展方法或或任何你喜欢的.ForEachList<T>IList<T>IEnumerable<T>

public static void ForEach<T>(this IList<T> list, Action<T> action)
{
    foreach (T t in list)
        action(t);
}
Run Code Online (Sandbox Code Playgroud)

你只需要警惕原始集合中的对象将被修改的事实,但我想命名确实暗示了这一点.

-------------------------------------------------- -------------------------------------------------- --------------------------------

我更喜欢打电话:

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .ForEach(n => AssignCitizenShip(n);
Run Code Online (Sandbox Code Playgroud)

foreach (var n in people.Where(p => p.Tenure > 5).Select(p => p.Nationality))
{
    AssignCitizenShip(n);
}
Run Code Online (Sandbox Code Playgroud)

如果是这样,您可以创建扩展方法IEnumerable.请注意,终止呼叫会ForEach执行Linq查询.如果你不想要它,你也可以通过使用yield语句并返回一个来推迟它IEnumerable<T>:

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
    foreach (T t in list)
    {
        action(t);
        yield return t;
    }
}
Run Code Online (Sandbox Code Playgroud)

这解决了副作用问题,但我个人喜欢一个名为ForEach最终执行调用的方法.

-------------------------------------------------- -------------------------------------------------- -------------------------------

为了解决喜好的反对意见,这里是一个更好的链路从埃里克利珀比这个.引用他:

"第一个原因是这样做违反了所有其他序列操作符所依据的函数式编程原则.显然,调用此方法的唯一目的是引起副作用.表达式的目的是计算一个值,不要引起副作用.声明的目的是引起副作用.这个东西的调用网站看起来很像一个表达式(但是,诚然,因为该方法是无效的返回,表达式只能可以在"语句表达式"上下文中使用.)我不能很好地创建唯一对其副作用有用的序列运算符.

第二个原因是,这样做会增加语言的新代表性能力".

埃里克并没有说这是件坏事 - 只是决定不在默认情况下包含构造的哲学原因Linq.如果您认为某个函数不IEnumerable应该对内容起作用,那么就不要这样做.就个人而言,我不介意,因为我很清楚它的作用.我将其视为导致集合类副作用的任何其他方法.如果我愿意的话,我也可以进入函数并调试它.这是另一个Linq自己.

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .AsParallel()
      .ForAll(n => AssignCitizenShip(n);
Run Code Online (Sandbox Code Playgroud)

正如我所说,这些并没有什么不好.它只是个人喜好.我不会将它用于嵌套foreachs,或者它是否涉及在foreach循环内部执行多行代码,因为这是不可读的.但是对于我发布的简单示例,我喜欢它.看起来干净简洁.

编辑:请参阅性能链接btw:为什么List <T> .ForEach比标准foreach更快?

  • @VirtualVoid是一种虚假声明; 徘徊在所显示的时间; 你的名单是"2012-12-19 06:35:45Z",nawfal列出了"2012-12-19 06:35:08Z".他实际上年纪大了. (5认同)
  • 因为你写了"Foreah",我正在与downvote的冲动作斗争......:P (2认同)

Pan*_*nis 6

您可以制作扩展方法并使用大部分实现void List<T>.ForEach(Action<T> action).您可以在Shared Source Initiative站点下载源代码.

基本上你会结束这样的事情:

public static void ForEach<T>(this IList<T> list, Action<T> action) 
{
    if (list == null) throw new ArgumentNullException("null");
    if (action == null) throw new ArgumentNullException("action");

    for (int i = 0; i < list.Count; i++)
    {
        action(list[i]);
    }
}
Run Code Online (Sandbox Code Playgroud)

它比使用该foreach语句的其他实现略胜一筹,因为它利用了IList包含索引器的事实.

虽然我对OR Mapper的答案很有帮助,但有时候在很多开发人员的大项目中,很难让每个人都认为foreach声明更清晰.更糟糕的是,如果您的API基于接口(IList)而不是具体类型(List),那么习惯的开发人员List<T>.ForEach method可能会开始调用ToList您的IList引用!我知道,因为它发生在我之前的项目中.我按照框架设计指南在我们的公共API中使用集合接口.我花了一段时间注意到许多不习惯这种情况的开发人员ToList开始以惊人的速度开始使用.最后,我将这个扩展方法添加到每个人都在使用的公共程序集中,并确保ToList从代码库中删除所有不必要的调用.

  • 是的,因为`list <T> .ForEach`不涉及任何转换(如'foreach`),这更快.这是一个相关的问题http://stackoverflow.com/questions/744085/why-is-listt-foreach-faster-than-standard-foreach?lq=1(并不意味着避免`foreach`是有意义的) (2认同)