List<T>.Find() returns the first element found that matches a given criteria. So lets say we have List<int> and we use the Find method on it. What will be the returned value? If a number in the list matches the criteria it will be returned, but what if not? what does the variable zero contains after executing this code:

List<int> listOfInts = new List<int>(new int[] { 1,2,3,4,5,6,7,8,9});
int zero = listOfInts.Find(
    delegate(int i)
        return i == 0;

It has the value of 0! What does that mean? Is 0 in the list? But when you think about it, what did I expect writing a code like this? Observing the implementation with reflector you can see that if no matching value is found, Find() will return default(T). The behavior of the default keyword is to return null if it’s a reference type or 0 if its a numeric value type. so it makes sense to use it with reference type, but if you are writing a generic class, and don’t know if it might be used with value types as well, I suggest to use the FindIndex instead.

Tags :

8 Responses to “Beware of List.Find()”

  1. Will

    Said on May 13, 2008 :

    Wow, that’s really… bad. Very bad. Extremely bad.

  2. bob

    Said on May 13, 2008 :

    I’m not really seeing the danger here. What would you expect it to return?

  3. Shahar Y

    Said on May 13, 2008 :

    Hi bob,

    The author didn’t say that there is a danger here. He only stated that List.Find() has a problem by design when it comes to value types and that using List.FindIndex() is more recommended.

  4. woro

    Said on May 13, 2008 :

    Suppose you have list with elements
    List list = new List(new int[]{0,1,2,3,4});

    Then if you try:

    int item = list.Find(0);

    You get 0 and you don’t know whether it is element of the list or default(int).

  5. mike

    Said on May 13, 2008 :

    Just RTFM (extract from MSDN help):
    “When searching a list containing value types, make sure the default value for the type does not satisfy the search predicate. Otherwise, there is no way to distinguish between a default value indicating that no match was found and a list element that happens to have the default value for the type. If the default value satisfies the search predicate, use the FindIndex method instead.”

    … which basically says: don’t search for 0 or null with Find !

  6. Will Asrari

    Said on May 13, 2008 :

    If you want to know whether the list contains a value just use List.Contains().

    if (list.Contains(0))

  7. Khalid Abuhakmeh

    Said on May 19, 2008 :

    turn your value types into nullables. That way you avoid the default(T) of a value type.

    List listOfInts = new List(new int?[] { 1,2,3,4,5,6,7,8,9});
    int? zero = listOfInts.Find(
    delegate(int i)
    return i.Value == 0;

    There you go, there is another solution.

1 Trackback(s)

  1. May 14, 2008: Dew Drop - May 14, 2008 | Alvin Ashcraft's Morning Dew

Post a Comment