Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any method like ForEach for IList? [duplicate]

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.

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.

Is there some alternative?

like image 869
Joe.wang Avatar asked Dec 19 '12 06:12

Joe.wang


People also ask

Can I use foreach in IEnumerable C#?

In C#, it is not strictly necessary for a collection class to implement IEnumerable and IEnumerator in order to be compatible with foreach . As long as the class has the required GetEnumerator , MoveNext , Reset , and Current members, it will work with foreach .

How do you foreach in Linq?

Convert a foreach loop to LINQ refactoringPlace your cursor in the foreach keyword. Press Ctrl+. to trigger the Quick Actions and Refactorings menu. Select Convert to LINQ or Convert to Linq (call form).

Does foreach work with lists?

Using the CodeThe ForEach method of the List<T> (not IList<T> ) executes an operation for every object which is stored in the list. Normally it contains code to either read or modify every object which is in the list or to do something with list itself for every object.


2 Answers

Use a foreach loop:

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.

like image 130
O. R. Mapper Avatar answered Sep 30 '22 10:09

O. R. Mapper


If your IList<T> is an array (T[]), then you have Array.ForEach method 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.

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:

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.

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

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

"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 philosophical reasons 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.

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 foreach loop since thats plain unreadable. But for simple example I posted, I like it. Looks clean and concise.

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

like image 30
nawfal Avatar answered Sep 30 '22 10:09

nawfal