C# IList 有没有像 ForEach 这样的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13946740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:11:31  来源:igfitidea点击:

Is there any method like ForEach for IList?

c#linqextension-methods

提问by Joe.wang

Possible Duplicate:
LINQ equivalent of foreach for IEnumerable<T>

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

List<T>has a method called ForEachwhich executes the passed action on each element of it.

List<T>有一个被调用的方法ForEach,它在它的每个元素上执行传递的动作。

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

names.ForEach(p =>  { Console.WriteLine(p); });

But what if namesis not a List<T>but an IList<T>? IList<T>doesn't have a method like ForEach.

但是如果names不是 a List<T>but anIList<T>呢?IList<T>没有像ForEach.

Is there some alternative?

有什么替代方案吗?

采纳答案by O. R. Mapper

Use a foreachloop:

使用foreach循环:

foreach (var p in names) {
    Console.WriteLine(p);
}

There is no reason to use delegates and extension methods all over the place if that doesn't actually improve readability; a foreachloop is not any less explicitly telling readers what's being done than a ForEachmethod.

如果实际上不能提高可读性,就没有理由到处使用委托和扩展方法;与方法相比,foreach循环同样明确地告诉读者正在做什么ForEach

回答by nawfal

If your IList<T>is an array (T[]), then you have Array.ForEachmethod on them similar to ForEachon List<T>. You can create an extension method for your custom IList<T>or IEnumerable<T>or whatever you prefer.

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

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

You just have to be wary of the fact that the objects in the original collection will be modified, but I guess the naming does imply that.

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

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

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

I prefer to call:

我更喜欢打电话:

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .ForEach(n => AssignCitizenShip(n);

than

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

If so you can create the extension method on IEnumerable. Mind you the terminating call ForEachexecutes the Linqquery. If you do not want it, you can defer it too by using yieldstatement and returning an IEnumerable<T>back:

如果是这样,您可以在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;
    }
}

That solves the side-effect issue, but I personally like a method named ForEachto finally execute the call.

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

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

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

To address the opposing views on preferences, here is a better linkfrom Eric Lippert than this. To quote him:

为了解决关于偏好的相反观点,这里有一个来自 Eric Lippert 的比这个更好的链接。引用他的话:

"The first reason is that doing so violates the functional programming principles that all the other sequence operators are based upon. Clearly the sole purpose of a call to this method is to cause side effects. The purpose of an expression is to compute a value, not to cause a side effect. The purpose of a statement is to cause a side effect. The call site of this thing would look an awful lot like an expression (though, admittedly, since the method is void-returning, the expression could only be used in a “statement expression” context.) It does not sit well with me to make the one and only sequence operator that is only useful for its side effects.

The second reason is that doing so adds zero new representational power to the language".

“第一个原因是这样做违反了所有其他序列运算符所基于的函数式编程原则。显然,调用此方法的唯一目的是引起副作用。表达式的目的是计算一个值,不要引起副作用。语句的目的是引起副作用。这个东西的调用点看起来非常像一个表达式(尽管,无可否认,由于该方法是返回空值的,该表达式只能用在“语句表达式”上下文中。)我不喜欢制作唯一一个仅对其副作用有用的序列运算符。

第二个原因是,这样做为语言增加了零新的表征能力”。

Eric's not saying it's a bad thing to do - just the philosophicalreasons behind the decision to not include the construct in Linqby default. If you believe a function on an IEnumerableshouldn't act on the contents, then don't do it. Personally I dont mind it since I'm well aware what it does. I treat it as any other method that causes side-effect on a collection class. I can enter into the function and debug it too if I want. Here is another one from Linqitself.

Eric 并不是说​​这样做是件坏事——只是默认情况下不包含该构造的决定背后的哲学原因Linq。如果你认为一个函数不IEnumerable应该对内容进行操作,那么就不要这样做。我个人不介意它,因为我很清楚它的作用。我将其视为对集合类产生副作用的任何其他方法。如果我愿意,我也可以进入该函数并对其进行调试。这是另一个来自Linq它自己。

people.Where(p => p.Tenure > 5)
      .Select(p => p.Nationality)
      .AsParallel()
      .ForAll(n => AssignCitizenShip(n);

As I would say, there is nothing bad about these. Its just personal preference. I wouldn't use this for nested foreachs or if it involves more than one line of code to execute inside the foreachloop since thats plain unreadable.But for simple example I posted, I like it. Looks clean and concise.

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

Edit:See a performance link btw: Why is List<T>.ForEach faster than standard foreach?

编辑:顺便看看性能链接:为什么 List<T>.ForEach 比标准 foreach 快?

回答by nawfal

Add this code to static class and call it extensions:

将此代码添加到静态类并将其称为扩展:

public static void ForEach<T>(this IList<T> list, Action<T> action) {
    foreach(var item in list) {
        action.Invoke(item);
    }
}

回答by Panos Rontogiannis

You could make an extension method and use most of the implementation of void List<T>.ForEach(Action<T> action). You can download the source code at the Shared Source Initiativesite.

您可以创建一个扩展方法并使用void List<T>.ForEach(Action<T> action). 您可以在Shared Source Initiative站点下载源代码。

Basically you will end to something like this:

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

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]);
    }
}

It is slightly better than the other implementations that use the foreachstatement since it takes advantage of the fact that IList includes an indexer.

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

Although I aggree with the answer of O. R. Mapper, sometimes in big projects with many developers it is hard to convicne everybody that a foreachstatement is clearer. Even worse, if your API is based on interfaces (IList) instead of concrete types (List) then developers that are used to the List<T>.ForEach methodmight start calling ToListon your IList references! I know because it happened in my previous project. I was using the collection interfaces everywhere in our public APIs following the Framework Design Guidelines. It took me a while to notice that many developers where not used to this and call to ToListstarted apprearing with an alarming rate. Finally I added this extension method to a common assembly that everybody was using and made sure that all unecessary call to ToListwere removed from the codebase.

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