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.
By Will on May 13, 2008 | Reply
Wow, that’s really… bad. Very bad. Extremely bad.
By bob on May 13, 2008 | Reply
I’m not really seeing the danger here. What would you expect it to return?
By Shahar Y on May 13, 2008 | Reply
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.
By woro on May 13, 2008 | Reply
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).
By mike on May 13, 2008 | Reply
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 !
By Will Asrari on May 13, 2008 | Reply
If you want to know whether the list contains a value just use List.Contains().
if (list.Contains(0))
{
}
By Khalid Abuhakmeh on May 19, 2008 | Reply
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)
{
if(i.HasValue)
return i.Value == 0;
});
There you go, there is another solution.