Click here to Skip to main content
13,557,707 members
Click here to Skip to main content
Add your own
alternative version


33 bookmarked
Posted 27 Oct 2008
Licenced CPOL

Using Find in a Generic List

, 27 Oct 2008
Rate this:
Please Sign up or sign in to vote.
This article investigates the use of List.Find() when using value and reference types, and how to use it when working with your own custom classes.



There're quite a few ways to find an object inside a Generic List, but we'll focus on one specific method List<T>.Find(), and investigate its behavior when working with value types and reference types.


While working with Generics the other day, I stumbled on a few things that are important to keep in mind when using the Find() method on a generic list. Especially when working with value types, and your search criteria is literally the default value returned when no results were found. I ended up discovering a few things about Find() and how to use it on your own custom classes. There's also a simple helper method that takes in an array of custom types and checks if the specified object was found.

I hope this helps someone understand a bit better on what's going on when using the Find() method on a Generic List.

More about List<T>.Find()

List<T>.Find Method - Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire List<T>.

A simple example is a generic list consisting of integers:

List<int> intList1 = new List<int>(new int[] {1,2,3,4});

int intResult = intList1.Find
    delegate(int intpar1){return intpar1 == 3}

which would basically return the integer if it was found in the list.

However, consider the response when the integer wasn't found:

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.

So, be careful when using .Find() when your search criteria is literally the default value for the type. (This is especially relevant when using value types.)

One way of handling this is to turn your value types into nullable types. That way, you can avoid 0 being returned when your integer wasn't found in the list:

List<Nullable<int>> intListTemp2 = new List<int?>
    new int?[] { 1, 2, 3, 4 }
int? intFoundAnon = intListTemp2.Find
    delegate(int? intInput1){return intInput1 == 5;}

Instead of 0, null is returned if the value wasn't found in the list of value types.

This can be very useful when working with database null values being used in columns that have types such as int or DateTime.

There's another thing to keep in mind when searching for a reference type inside a list:

Reference equality vs. value equality

Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality.

Reference equality means that there are not two objects to compare. Instead, there are two object references, and both of them refer to the same object.

When you are doing a .Find() on a value type (such as int, bool, char, DateTime, enum, Decimal, ..), the elements are compared based on the value itself. But, if you do a .Find() on a reference type (like a custom class), you'd be looking for objects that have the same reference.

To explain it more: even if you compare two objects with the same values for all properties, it won't necessarily return true.

Patient patTemp1 = new Patient("John");
Patient patTemp2 = new Patient("John"); 

// this will return false
bool blResult = patTemp1.Equals(patTemp2);

Instead, you should make sure your custom class overrides the Equals() method and define how the two objects should be compared.

class Patient : IComparable
public override bool Equals(object obj)
    return this.Firstname == ((Patient) obj).Firstname;

And, remember to make sure your custom class inherits from the interface "IComparable" as well.

If you remember to do that, you can do a Find() on your Generic List and it will play along as expected (won't return false every time).

List<Patient> PatientList = new List<Patient>
    new Patient[] 
        new Patient("John Smith"), new Patient("Victor Matfield")  

bool blresult = PatientList.Exists
    delegate(Patient pTempSearch) 
        return pTempSearch.Equals(new Patient("John Smith"));  

The following helper method takes in an array of custom types and checks if the specified object was found.

public bool ArrayContains<T>(T[] array, T value) 
    return array != null && 
    Array.Exists(array, delegate(T tTemp) 
        return tTemp.Equals(value);

bool blResult = ArrayContains<Patient>(PatientArray, Patient1);

Points of Interest

The code example included covers everything in a bit more depth. If you're like me, looking at the actual code will give some additional insight.

Also, note the use of Nullable Types when using Find() on value types such as Int32.


This is the first post and release.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior)
South Africa South Africa
I'm a senior software developer from South Africa and have a huge passion for .NET and Microsoft related technologies.

When I'm not having fun figuring out an architecture or class design, you'd probably find me rocking on the drums, running around with my badminton racquet or enjoying another bitter coffee or an ice-cold Amstel at the bar.

You may also be interested in...


Comments and Discussions

GeneralThe IEquatable Interface versus bool Equals(obj) Pin
Martin.Holzherr30-Oct-08 0:50
memberMartin.Holzherr30-Oct-08 0:50 
GeneralRe: The IEquatable Interface versus bool Equals(obj) Pin
johan_vw30-Oct-08 3:43
memberjohan_vw30-Oct-08 3:43 
Hi Martin,

Thanks for the feedback and posts - it sounds like you know your way around Generics and enjoy them as well. You mentioned quite a few very interesting points, and I wasn't aware of the performance boost when including support for IEquatable<t> inside a custom class/struct. Thank you for pointing that one out.

The article tried to illustrate the necessity of overriding the 'Equals' method when trying to compare two reference objects. To override the Equals method (which is in turn used when calling Find()) you only need to inherit from IComparable.

It's true, my implementation of the 'Equals' method didn't cater for necessary checks on the obj parameter and one would definately be better of making use of the check you suggested.

The article also mentions another usefull link "overrides the Equals() method" that also have a few guidelines for overriding Equals(). Another step to improve the code would've been to introduce exception handling as well.

You've pointed out two very important points, thanks again for the feedback.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180515.1 | Last Updated 28 Oct 2008
Article Copyright 2008 by johan_vw
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid