Home Contact

X

Coder, not artist.

News

Current archive is at: http://cskardon.wordpress.com/ - I aim to move it all soon! All code on here is free, but as a consequence it's up to you to check it, ha! If you have any questions, feel free to email: cskardon -- @ -- xclave dot co dot uk I'm sure you can decrypt the address there!

Twitter












Archives

Post Categories

Image Galleries

Syndication:

EntitySet.Contains – uses Reference comparisons - Addendum

I realised whilst reviewing some code that you can also implement the IEquatable<T> interface as well just overriding the Equals (or indeed, in place of doing that).

So, back to our Simple class, we could actually write it as such:

internal class Simple : IEquatable<Simple>
{
    public int TheInt { get; set; }
    public string TheString { get; set; }
 
    public Simple(int theInt, string theString)
    {
        TheInt = theInt;
        TheString = theString;
    }
 
    public bool Equals(Simple other)
    {
        if(other == null)
            return false;
 
        return TheInt == other.TheInt && string.Equals(TheString, other.TheString);
    }
}
 

This will work perfectly in a collection situation (though again, not the EntitySet), but will fail with the extension method we wrote last time… How?

Well, let’s say we perform the same test as in the last post:

public static void Run()
{
    EntitySet<Simple> simpleEs = new EntitySet<Simple>
                             {
                                 new Simple(1, "1"),
                                 new Simple(2, "2")
                             };
 
    Simple s2 = new Simple(2, "2");
    
    Console.WriteLine("Contains ES? " + simpleEs.Contains(s2));
    Console.WriteLine("Contains ES? " + simpleEs.ContainsUsingEquals(s2));
}

We will get the output:

Contains ES? false
Contains ES? false

Which isn’t what we want. Clearly when in our extension method we call:

e.Equals(t)

We are only calling the normal Equals method. We could modify this to read:

((IEquatable<T>)e).Equals(t)

Which would work as long as it was IEquatable<T> (in which case we’d be better off forcing our extension method to only work on objects implementing that interface:

public static bool ContainsUsingEquals(this EntitySet<T> es, T t)
    where T : class, IEquatable<T>
{ /**/ }

But that seems a bit limiting, so instead I modified the extension to just cover both scenarios. It will attempt to use the IEquatable<T> implementation first, and it that’s not there, use the original equals:

 

public static bool ContainsUsingEquals<T>(this EntitySet<T> es, T t)
    where T : class
{
    if (t is IEquatable<T>)
    {
        foreach (var e in es)
            if (((IEquatable<T>)t).Equals(e))
                return true;
    }
    else
    {
        foreach (var e in es)
            if (t.Equals(e))
                return true;
    }
    return false;
}

Of course it might be more efficient to do the cast of the ‘t’ to IEquatable<T> earlier and use the casted version rather than casting it each time…

meh


Feedback

No comments posted yet.


Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: