What you want to see on DotNetFunda.com ?
Go to DotNetFunda.com
Twitter TwitterLinkedIn
YouTubeGoogle
 Online : 8410 |  Welcome, Guest!   Register  Login
Home > Articles > C# > List(T).ForEach or foreach, it doesn't matter...or does it?

List(T).ForEach or foreach, it doesn't matter...or does it?

Article posted by Baldi on 6/14/2010 | Views: 4028 | Category: C# | Level: Beginner red flag


When you use a List, it doesn't matter if you use the ForEach method of the generic list or use a normal foreach or does it? Sometimes it makes a difference!

Introduction

In C# you have various possibilities to iterate over a list like for loop, foreach loop or with LINQ. When you use a List(T) type you have even one more, the ForEach method. But this method doesn't show always the same behaviour than a normal foreach loop.

Using the code 

The 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.

Modify the object itself

The following sample with a ForEach method loops over all stored Points in the collection. It substracts 10 from the x coordinate of the point. At the end the Points will be printed to the console.

List<Point> points = new List<Point>(){ new Point(14, 10), new Point(19, 10) };

items.ForEach(point => point.X = point.X - 10);

foreach (Point point in points)
{
Console.WriteLine(point);
}

The output in the console is in this case {X=14, Y=10} and {X=19, Y=10}. I expected that X is 4 and 9, so what's wrong? If you put the same logic into a normal foreach statement the compiler throws the following error: "Cannot modify members of 'point' because it is a 'foreach iteration variable'". If we define our own type, the code does what it should do! 

public class MyPoint
{
public MyPoint(int x, int y){ X = x; Y = y; }
public int X{ get; set; }
public int Y{ get; set; }
}

List<MyPoint> points = new List<MyPoint>(){ new MyPoint(14, 10), new MyPoint(19, 10) };

items.ForEach(point => point.X = point.X - 10);

foreach (MyPoint point in points)
{
Console.WriteLine(point);
}

The difference is, that Point is a value type, a struct, and MyPoint is a reference type. So in the case where Point is used, a copy of the object is passed to the method, not the object itself. So if the action, which is passed into the ForEach method, changes the copy, but it won't affect the original object.

Modify the collection

When you use a normal foreach statement, you can't add or remove items while iterating over the collection. But with List.ForEach you can, so the following code can be executed without any errors. Which result do you expect?

public class Integer
{
public int Value { get; set; }
public Integer(int value) { Value = value; }
}

public void Sample()
{
List<Integer> items = new List<Integer>()
{
new Integer(14),
new Integer(0),
new Integer(19)
};

items.ForEach(item =>
{
if (item.Value == 0)
{
items.Remove(item);
}
item.Value = item.Value - 10;
});

foreach (Integer item in items)
{
Console.WriteLine(item.Value);
}
}

The result which is shown in the console is 4 and 19. So this is a good example that not all what you can do, you also should do! The result should be 4 and 9! It seems that internally a for loop is is used, which iterates backward over the collection. 

Conclusion

So List<T>.ForEach allows several things which is blocked in a foreach loop. These things aren't allowed for a good reason. So if you want to store objects of value types, like int, long, double, bool or even string,  in a generic List, you shouldn't use the ForEach method if you want to avoid problems. A good solution is use a for loop and access the data over the indexer of the collection. Also removing items in the ForEach method is a thing which should be avoided also when it is possible. 

If you like this article, subscribe to our RSS Feed. You can also subscribe via email to our Interview Questions, Codes and Forums section.

Page copy protected against web site content infringement by Copyscape
Found interesting? Add this to:



Please Sign In to vote for this post.

Experience:7 year(s)
Home page:http://www.mbaldinger.com
Member since:Tuesday, May 25, 2010
Level:Starter
Status: [Member]
Biography:
>> Write Response - Respond to this post and get points
Related Posts

Parameters in C#: In C Sharp(C#) we can have three types of parameters in a function. The parameters can be In parameter (which is not returned back to the caller of the function), Out parameter and ref parameter (where by a reference to the variable is passed back).

We will see how to work with files and directories

Windows Services is the most important feature for the long standing applications to run services automatically soon after the system boots.We can manually control these Services by starting and stoping at a specific time.

This article discusses few techniques in maintaining data in memory for quick access. A sample CacheManager implementation is shown with this article for C# Console/Windows applications usage.

The article describes most of the common Design patterns we often require while we do our code, using C#.

More ...
About Us | Contact Us | The Team | Advertise | Software Development | Write for us | Testimonials | Privacy Policy | Terms of Use | Link Exchange | Members | Go Top
General Notice: If you find plagiarised (copied) contents on this page, please let us know the original source along with your correct email id (to communicate) for further action.
Copyright © DotNetFunda.Com. All Rights Reserved. Copying or mimicking the site design and layout is prohibited. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks. | 5/26/2013 5:07:26 AM