Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ((object)(int)1).Equals(((object)(ushort)1)) yield false?

I have the Situation that I have an object which I want to check for equality with another object.

public static bool Equals(object a, object b)
{
    return a.Equals(b);
}

A Problem occurs when a = 1 (integer) and b = 1 (ushort (or basically not integer)). I wondered whether this shouldn't yield true, but it does return false...

Edit

What makes it even worse is this:

Hashtable ht = new Hashtable();
ht.Add((int)1, "SOME STRING");
ht.Add((short)1, "SOME STRING");
ht.Add((long)1, "SOME STRING");

I think that the value '1' should only be allowed once.

like image 518
HerpDerpington Avatar asked Aug 14 '14 10:08

HerpDerpington


Video Answer


2 Answers

Int32.Equals(object) returns true only if the other object is also an instance of Int32:

true if obj is an instance of Int32 and equals the value of this instance; otherwise, false.

In code (ILSpy, .NET 4):

public override bool Equals(object obj)
{
    return obj is int && this == (int)obj;
}

Since obj is int returns false you get a false.

Edit: ragarding to your edit(Hashtable with "similar" keys): if you don't want to allow duplicate objects use a Dictionary<int, string> instead(preferred) or add only ints to the HashTable.

like image 171
Tim Schmelter Avatar answered Oct 12 '22 12:10

Tim Schmelter


Here's a simple class and implementation of equality comparers. As you can see, the standard apporach for equals is to make sure they are of the same time first, and then, that the inside matches (in our case, a string and a date).

If you want something else, you can always override it to your heart content, and cast both sides to something you're happy with :)

public struct InputEntry
{
    public DateTime Date { get; set; }
    public string Entry { get; set; }

    public bool Equals(InputEntry other)
    {
        return Date.Equals(other.Date) && string.Equals(Entry, other.Entry);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is InputEntry && Equals((InputEntry) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return ( Date.GetHashCode()*397) 
                   ^ (Entry != null ? Entry.GetHashCode() 
                                    : 0);
        }
    }

    public static bool operator ==(InputEntry left, InputEntry right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(InputEntry left, InputEntry right)
    {
        return !left.Equals(right);
    }

    private sealed class EntryDateEqualityComparer 
                                    : IEqualityComparer<InputEntry>
    {
        public bool Equals(InputEntry x, InputEntry y)
        {
            return string.Equals(x.Entry, y.Entry) && x.Date.Equals(y.Date);
        }

        public int GetHashCode(InputEntry obj)
        {
            unchecked
            {
                return ( (obj.Entry != null ? obj.Entry.GetHashCode() : 0)*397) 
                       ^ obj.Date.GetHashCode();
            }
        }
    }

    private static readonly IEqualityComparer<InputEntry> 
                  EntryDateComparerInstance = new EntryDateEqualityComparer();

    public static IEqualityComparer<InputEntry> EntryDateComparer
    {
        get { return EntryDateComparerInstance; }
    }
}
like image 31
Noctis Avatar answered Oct 12 '22 11:10

Noctis