Implicit casting of an object into a string, for use in a hashtable

Say we have this class:

public class Moo { string _value; public Moo(string value) { this._value = value; } public static implicit operator string(Moo x) { return x._value; } public static implicit operator Moo(string x) { return new Moo(x); } public override bool Equals(object obj) { if (obj is string) return this._value == obj.ToString(); else if (obj is Moo) return this._value == ((Moo)obj)._value; return base.Equals(obj); } public override int GetHashCode() { return _value.GetHashCode(); } } 

If I add an object of this type to the Hashtable, I can find the object using an identical string.
But if the hashtable contains a string, not an object, it does not find it when passing the object.

 Moo moo = new Moo("abc"); bool result1 = moo == "abc"; //true bool result1a = moo.Equals("abc"); //true bool result2 = "abc" == moo; //true bool result2a = "abc".Equals(moo); //true bool result2b = ((object)"abc").Equals(moo); //false Hashtable hash = new Hashtable(); hash[moo] = 100; object result3 = hash[moo]; //100 object result4 = hash["abc"]; //100 hash = new Hashtable(); hash["abc"] = 100; object result5 = hash[moo]; //null!!!! object result6 = hash["abc"]; //100 

I tried to override the == operator, and that didn't matter.
Is it possible to use implicit casting in a hashtable this way?

+6
source share
2 answers

Firstly, why are you using a hash table and not a generic Dictionary<,> ?

Regardless, your problem is that the hash table calls ((object)"abc").Equals(moo) , which returns false, of course. You can override this behavior by passing your own implementation of IEqualityComparer one of the HashTable constructors with the IEqualityComparer parameter.

Since, as you already noted, you are trying to avoid changing obsolete code, you may not be able to replace the existing hash table with those who have custom IEqualityComparer. If this is true, then I think the answer is that you cannot do what you would like to do.

Since you are developing this "moo" class, I assume that you have control over the code that passes the moo class to the index index of the hash table. If this is true, you can simply call ToString() on the object you pass to the index, and, of course, override ToString in Moo .

+5
source

Thus, implicit garbage does not matter. They will not do anything. You will get exactly the same results if you comment on them. The Equals and GetHashCode methods are important here.

So your GetHashCode method is great. Two objects (be it a string or moo) will always have the same hash if they should be the same, so it will work. Your problem is with your equals method.

moo.Equals("abc") will return true.

 object obj = moo; "abc".Equals(obj) 

will return false; "abc".Equals(moo) will only return true because there is an implicit statement that converts moo to a string and uses Equals string overloading rather than overloading the Equals object. Because the Hashtable will store everything as an object, it will always use the object overload of the Equals method. (The == operator is not used, it uses the Equals method in the dictionary.) This is because the string Equals method will check that the passed object is a string, and it will return false if it is not.

Solution: You do not need to use the default constructor for HashTable. What you need to do is use a custom IEqualityComparor so that it does not use the Equals method of the object itself. This is not so difficult to do. Just create a new class that extends IEqualityComparer and gives it an equals method, which is basically the same as your moo Equals method, so that it will perform the comparison correctly no matter what type or object it is.

+4
source

Source: https://habr.com/ru/post/910191/


All Articles