Home > Back-end >  How does the List<T>.ForEach(Action<T> action) method actually work?
How does the List<T>.ForEach(Action<T> action) method actually work?

Time:10-17

I've looked at the documentation of the List.ForEach(Action action) method but it only says what it does, not how it does it. I know it takes an action and performs that action on all of the elements of the list. But what is the actual code that it uses to accomplish this? Is there a way I could make my own ForEach method that works the same way as the lists ForEach method?

I have had times in the past where I want to condense my ForEach loops and this looks like it would work well in some of those circumstances, especially when I'm using custom classes.

CodePudding user response:

I'll extract if from the c# source code, which is published online on a dedicated site at MS and also on GitHub - useful resources to bookmark:

 public void ForEach(Action<T> action) {
        if( action == null) {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
        }
        Contract.EndContractBlock();

        int version = _version;

        for(int i = 0 ; i < _size; i  ) {
            if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
                break;
            }
            action(_items[i]);
        }

        if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
            ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
    }

Mostly it's just fluff for version checking and throwing, the core part is a for loop that takes the method you provided and invokes it passing in every list item in turn:

    public void ForEach(Action<T> action) {

        for(int i = 0 ; i < _size; i  ) {
            action(_items[i]);
        }

    }

You absolutely can write it yourself in your own classes, and it would look just like that. This is the .NET framework version - the core version won't be vastly different

Note that it's not a huge char saving:

foreach(var v in vList) myMethod(v);
vList.ForEach(myMethod);

foreach(var v in vList)
  if(v.X > 10)
    Console.WriteLine(v.Y);

vList.ForEach(v => {
  if(v.X > 10)
    Console.WriteLine(v.Y);
});

And foreach remains fairly readable for most as it gets longer, whereas when you start getting into multi line lambda they can end up a bit more messy looking and not significantly more condensed

  • Related