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
Is there any method like ForEach for IList?
提问by Joe.wang
Possible Duplicate:
LINQ equivalent of foreach for IEnumerable<T>
List<T>
has a method called ForEach
which 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 names
is 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 foreach
loop:
使用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 foreach
loop is not any less explicitly telling readers what's being done than a ForEach
method.
如果实际上不能提高可读性,就没有理由到处使用委托和扩展方法;与方法相比,foreach
循环同样明确地告诉读者正在做什么ForEach
。
回答by nawfal
If your IList<T>
is an array (T[]
), then you have Array.ForEachmethod on them similar to ForEach
on 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方法,类似于ForEach
on 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 ForEach
executes the Linq
query. If you do not want it, you can defer it too by using yield
statement 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 ForEach
to 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 Linq
by default. If you believe a function on an IEnumerable
shouldn'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 Linq
itself.
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 foreach
s or if it involves more than one line of code to execute inside the foreach
loop since thats plain unreadable.But for simple example I posted, I like it. Looks clean and concise.
正如我所说,这些没有什么不好。这只是个人喜好。我不会将它用于嵌套的foreach
s 或者如果它涉及多行代码在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 foreach
statement 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 foreach
statement 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 method
might start calling ToList
on 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 ToList
started 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 ToList
were removed from the codebase.
虽然我同意 OR Mapper 的回答,但有时在有很多开发人员的大项目中,很难让每个人都相信一个foreach
声明更清晰。更糟糕的是,如果您的 API 基于接口 (IList) 而不是具体类型 (List),那么习惯于的开发人员List<T>.ForEach method
可能会开始调用ToList
您的 IList 引用!我知道是因为它发生在我之前的项目中。我在遵循框架设计指南的公共 API 中随处使用集合接口。我花了一段时间才注意到许多开发人员不习惯这一点,并ToList
开始以惊人的速度开始申请。最后,我将此扩展方法添加到每个人都在使用的公共程序集中,并确保所有不必要的调用ToList
已从代码库中删除。