buddybubble
buddybubble

Reputation: 1319

Why is List<T>.Exists slower than a foreach loop?

I'm in WinForms and before saving changes to the DataBase, I had to check whether the used ErrorProvider holds an error for any of the displayed Controls.

I figured out several ways to do that among them:

Right from the stomache I expected the second to be the fastest, but using the Eqatec Profiler I discovered, that the foreach loop is slightly faster (in my case about 1ms). While this is insignificant, I still wonder why this happens?

How does the compiler translate these methods and why is the first one faster?

Upvotes: 0

Views: 853

Answers (3)

Alberto
Alberto

Reputation: 543

If you are using the function SetError in the Controls inside ctrlcontainer then you could track when an error has occurred. I would suggest either extending the class ErrorProvider with your customized class or including that provider inside one of your classes so you can override the SetError method i.e. you don't need to check anything and therefore the comparison between Exists and foreach is not relevant.

Upvotes: 0

Maarten
Maarten

Reputation: 22945

Why would you expect the List.Exists method to be faster? In essence it does the same as your manual check, but one thing it does do extra, is the check using a Predicate instead of a direct check. This must cost a little performance.

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460138

It is probably 1 ms slower in your case because List<T>.Exists calls FindIndex which is implemented in the following way:

public int FindIndex(int startIndex, int count, Predicate<T> match)
{
    if (startIndex > this._size)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
    }
    if (count < 0 || startIndex > this._size - count)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
    }
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    int num = startIndex + count;
    for (int i = startIndex; i < num; i++)
    {
        if (match(this._items[i]))
        {
            return i;
        }
    }
    return -1;
}

So this is a little bit more than a simple foreach.

Upvotes: 5

Related Questions