Determine if a sequence contains a certain element with LINQ C#
June 4, 2014 Leave a comment
Say we have the following string list:
string[] bands = { "ACDC", "Queen", "Aerosmith", "Iron Maiden", "Megadeth", "Metallica", "Cream", "Oasis", "Abba", "Blur", "Chic", "Eurythmics", "Genesis", "INXS", "Midnight Oil", "Kent", "Madness", "Manic Street Preachers" , "Noir Desir", "The Offspring", "Pink Floyd", "Rammstein", "Red Hot Chili Peppers", "Tears for Fears" , "Deep Purple", "KISS"};
If you’d like to check if a certain string element is present in the sequence then you can use the Contains operator in LINQ:
bool contains = bands.Contains("Queen"); Console.WriteLine(contains);
This yields true as you might expect.
This was a straightforward case as .NET has a good built-in implementation of string equality. It works just as well with primitive types like int or long. .NET can determine if two integers are equal so the default version of Contains is sufficient.
It is different with your custom objects, such as this one:
public class Singer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int BirthYear { get; set; } }
Consider the following list:
IEnumerable<Singer> singers = new List<Singer>() { new Singer(){Id = 1, FirstName = "Freddie", LastName = "Mercury", BirthYear=1964} , new Singer(){Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954} , new Singer(){Id = 3, FirstName = "Chuck", LastName = "Berry", BirthYear = 1954} , new Singer(){Id = 4, FirstName = "Ray", LastName = "Charles", BirthYear = 1950} , new Singer(){Id = 5, FirstName = "David", LastName = "Bowie", BirthYear = 1964} };
…and the following code:
Singer s = new Singer() { Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954 }; bool containsSinger = singers.Contains(s); Console.WriteLine(containsSinger);
This will of course yield false as equality is based on references and there’s no element in the sequence with the same reference as “s”. In this case we can use the overloaded version of Contains where you can supply an equality comparer:
public class DefaultSingerComparer : IEqualityComparer<Singer> { public bool Equals(Singer x, Singer y) { return x.Id == y.Id; } public int GetHashCode(Singer obj) { return obj.Id.GetHashCode(); } }
So equality is based on the ID. We can rewrite our query as follows:
Singer s = new Singer() { Id = 2, FirstName = "Elvis", LastName = "Presley", BirthYear = 1954 }; bool containsSinger = singers.Contains(s, new DefaultSingerComparer()); Console.WriteLine(containsSinger);
…which yields true.
You can view all LINQ-related posts on this blog here.