Introduction
The IEnumerable
interface provides enough methods and overloads originally and later .NET 3.5 added a huge set of enhancements via extension methods. There are very few cases were a programmer need to kick-in and get his hand dirty to create something which could be used across application development regardless of business or domain.
Majority
of the time, when we perform operations on IEnumerable
collections we deal with
same object type, or did my life just happened to be like that in past?...
Anyway, recently I started seeing a lot of cases where I need to compare or get the instance of an object using a different type. E.g.: To Search/Get the
location details of an Employee in a building-space collection, where I have the location collection and the Employee object in hand, and wished I could do something like lstLocation.Exists(employ)
.
Background
Before
this library, when I come across such an instance I do not have any alternative
but just get out of any built-in methods or LINQ facilities and then write a loop
to compare the objects explicitly. Sometimes LINQ helped me here but then I had to
struggle with collections from LINQ results for such a simple task. So later I
decided to write an extension method which could do the operation for me
easily, which I am sharing here. I found these methods are mostly a plus when
dealing with LINQ generated anonymous objects, where the original values can no
longer be used in any of the operations.
Demo / Results Screen
Using the code
Just add the compiled assembly or class library project to your solution and the extension methods will appear in all instances which
implements IEnumerable
. Refer below for method signatures.
A quick picture of the code
I do not want to give the whole code in the article itself to make it lengthy and boring. What about some short narrations and let you download the code and see it running?
Project 1: System.Collections.GlobalEquality
The Library consists of four modules.
GenericEqualityComparer<T>
:
I do not claim the ownership of this module. Essentially, this is where I started with the new library. It serves as a global comparer when
dealing with same instance type as of the collection. This class helps you to use a dummy object and avoid writing equality comparer for every case. But this works only only if you are dealing with the same type. Simply use this class to create an instance of comparer wherever .NET Framework asks for an IEqualityComparer
to be passed to the collections.
Eg: new GenericEqualityComparer<Artist>((x, y) => { return
x.ID == y.ID; })
IEqualityComparer<in Source, in Destination>
: Base interface, in case anyone wants further
extension.
GenericEqualityComparer<Source, Destination>
: This is the core of the library which allows the
comparison of two types of objects. The extension methods are provided in
library itself which consumes this class. In most cases you do not need to use this class directly; just go with the extension methods. Again yes,
you definitely want to make use of this guy in case you think about extending
these classes or adding more extension methods.
Extensions
: The methods of
this class will be added as extension methods to all the instances of
IEnumerable
.
Contains
= Determines whether the
specified object is available in the source collection using an external reference
and condition. Contains two overloads.
albums.Contains(artists[0], (x, y) => { return x.ArtistID == y.ID; })
GetItemBy
= Compares the any given
object by the provided comparer and returns the matching object from the source
collection. Contains two overloads.
albums.GetItemBy(artists[0], (x, y) => { return x.ArtistID == y.ID; }).AlbumName
IndexOfBy
= Compares the any given object by the provided comparer and returns the matching object from the source collection. . Contains two overloads.
albums.IndexOfBy(artists[0], (x, y) => { return x.ArtistID == y.ID; })
Any
= Determines whether any of
the specified objects are available in the source collection. Contains two
overloads.
albums.Any(artists, (x, y) => { return x.ArtistID == y.ID; })
All
= Determines whether all the specified objects are available in the source collection. Contains two overloads.
albums.All(artists, (x, y) => { return x.ArtistID == y.ID; })
Except
= Produces the set difference of two sequences by using the specified
IEqualityComparer
. Contains two overloads.
albums.Except(artists, (x, y) => { return x.ArtistID == y.ID; })
Project 2: GenericEqualityTest
This solution also include a test module which the results are shown in the above screenshot. It consists of three classes.
- Program – Main demo
- Artist – Support class to create
collection
- Album – Support class to create
collection
Download source code for complete library and demo. Add
comments for improvements and bugs.
History