The custom implements an equality comparison of two objects, one of which is overriding the Equals method of the object class, very easy, and returns false if equality returns TRUE. However, if a custom equality comparison is used for a generic set, such as dictionary, HashSet, and so on, these collections have one thing in common-the uniqueness of the stored item must be identified-that is, each subkey has a corresponding key.
Object. The Equals method is object-oriented, and if it is used for generic objects, a large number of boxing/unboxing operations, especially composite types, are required for the process of determining equality, and because of the careful comparison, the type conversions are more frequent, which leads to a certain amount of performance overhead, so For equality comparisons of generic collections, you should consider using the Iequalitycomparer<t>,dotnet type to provide an abstract class--equalitycomparer<t> that implements the interface.
In practical use, it may be possible to implement this abstract class directly, the advantage is that the abstract class exposes a static default property, you can return to the platform default comparison scheme. Therefore, the benefit of implementing this abstract class is that you can provide both a custom implementation and a default behavior.
Let's start by explaining why a custom equality comparison is required in a generic collection. For example, let's take the usual dictionary as an example, the key of the dictionary is identified by a class called entity, which is defined as follows.
Public class Entity { publicintgetset;} Public string Get Set ; } }
We then instantiate a dictionary and add two items to it.
Idictionary<entity,string> dic =NewDictionary<entity,string> (); Dic. ADD (NewEntity {ID =1, Name ="Xiao Ming"},"C + +"); Dic. ADD (NewEntity {ID =2, Name ="Xiao Wang"},"VB");
Next, read from the dictionary key is id = 2, Name = "Xiao Wang" value.
New Entity { 2, " Xiao Wang " }; if (DIC. ContainsKey (FindKey)) { Console.WriteLine (Dic[findkey]); }
When looking, instantiate an entity, then assign the ID and name attribute to the value you want to find, then call the ContainsKey method of the dictionary instance to determine if the key to be found exists in the dictionary, and if it exists, output the value corresponding to that key.
The code looks perfect, but once it's running, you'll find nothing. Why is it?
Because the key of the dictionary store item is our custom entity class, when we want to find it, we instantiate an entity object and assign the corresponding property value to find it, but the problem comes, we instantiate the FindKey object, The entity that is stored in the dictionary is not the same object, although their property values are equal, but they do not refer to the same instance because they are judged to be unequal, so the corresponding key cannot be found.
At this point, Equalitycomparer comes in handy, customizing a class and deriving from it, adding your own code implementations, whether or not the same object instance, as long as the value of the property is equal, is considered the same key.
Public Sealed classCustomeqcomparer:equalitycomparer<entity> { Public Override BOOLEquals (Entity x, entity y) {if(X.id = = Y.id && X.name = =y.name)return true; return false; } Public Override intGetHashCode (Entity obj) {returnobj.id. GetHashCode (); } }
Implement the Equals method if two objects are equal and return true, otherwise false is returned. The GetHashCode method returns a hash value, and the algorithm should not be too complex to avoid performance overhead, as long as the equivalent two objects are guaranteed to return the same hash value, and unequal objects return different hash values, so it is possible. The value of the id attribute is hashed directly here, so the ID value of each key cannot be duplicated.
Once you have customized the comparer, you can simply pass the constructor to it when you instantiate the dictionary instance. Change the code above to read:
New customeqcomparer (); IDictionarystringnewstring> (comp);
Now, again, the previous example, Id=2,name= "Xiao Wang" key can be found out.
The complete demo code is as follows:
classProgram {Static voidMain (string[] args) {Customeqcomparer Comp=NewCustomeqcomparer (); IDictionary<entity,string> dic =NewDictionary<entity,string>(comp); Dic. ADD (NewEntity {ID =1, Name ="Xiao Ming"},"C + +"); Dic. ADD (NewEntity {ID =2, Name ="Xiao Wang"},"VB"); Entity FindKey=NewEntity {ID=2, Name="Xiao Wang" }; if(DIC. ContainsKey (FindKey)) {Console.WriteLine (Dic[findkey]); } console.read (); } } Public classEntity { Public intID {Get;Set; } Public stringName {Get;Set; } } Public Sealed classCustomeqcomparer:equalitycomparer<entity> { Public Override BOOLEquals (Entity x, entity y) {if(X.id = = Y.id && X.name = =y.name)return true; return false; } Public Override intGetHashCode (Entity obj) {returnobj.id. GetHashCode (); } }
. NET deep breaths equalitycomparer--custom equality comparison