157 recommendations for writing high-quality code to improve C # programs--recommendation 12: overriding equals When overriding GetHashCode

Source: Internet
Author: User

Recommendation 12: Rewrite GetHashCode when overriding equals

Overriding the Equals method is not recommended unless you consider that a custom type will be used as the key value for a hash-based collection, because this brings up a series of problems.

If you compile the type of person in the previous recommendation, the compiler will prompt such a message:

"Overriding Object.Equals (Object O) but not overriding Object.GetHashCode ()"

If you override the Equals method without overriding the GetHashCode method, some potential bugs may be implied when using the dictionary class, such as the FCL. Or to encode the person in the previous recommendation, the code looks like this:

    StaticDictionary<person, personmoreinfo> personvalues =Newdictionary<Person , Personmoreinfo>(); Static voidMain (string[] args)          {Addaperson (); Person Mike=NewPerson ("NB123"); //Console.WriteLine (Mike.  GetHashCode ()); Console.WriteLine (Personvalues.containskey (Mike)); }           Static voidAddaperson () {person Mike=NewPerson ("NB123"); Personmoreinfo Mikevalue=NewPersonmoreinfo () {someinfo ="Mike ' s info" };          Personvalues.add (Mike, Mikevalue); //Console.WriteLine (Mike.  GetHashCode ()); Console.WriteLine (Personvalues.containskey (Mike)); } 

The output of this section of the code will be:

True

False

In theory, we have rewritten the Equals method of person in the previous recommendation, that is, Mike and the Main method in the Addaperson method are "value equal." It would be a matter of course to put the "value" as a key into the dictionary and then take the mikevalue out of it somewhere according to Mike. However, from the code snippet above, we found that the conclusion is correct for the same example, and that the result is problematic for different Mike examples.

A set of key values, such as the dictionary above, looks up value values based on the key value. This lookup is optimized internally by the CLR, which in effect looks for the value values based on the hashcode of the key value. When the code runs, the CLR first invokes the GetHashCode of the person type, and the CLR eventually calls the GetHashCode method of object because it discovers that the person does not implement GetHashCode. By removing the two lines of comment code from the above code and running the program output, we will find that the main method and the Addaperson method of the two Mike Hashcode are different. There is a need to explain why the object.gethashcode of the two actually correspond to the call will be different.

Object provides the default implementation of GetHashCode for all CLR types. Every new object, the CLR generates a fixed integer value for the object that does not change during the lifetime of the object, and the default GetHashCode implementation of the object is to hashcode the integer value. So, in the above code, the two Mike objects, although the property values are consistent, are inconsistent with the hashcode of their default implementations, which results in an unusual behavior in dictionary. To fix the problem, you must override the GetHashCode method. A simple rewrite of the person class can be in the following form:

     Public Override int GetHashCode ()      {          returnthis. Idcode.gethashcode ();      

The output of the code at the beginning of this article is then run, and the hashcode of the two will be found to be consistent, and the dictionary will find the corresponding key value, output: True.

The attentive reader may have discovered a problem that the Idcode property of the person class is a read-only property. The Idcode can be set to writable from the syntax itself, but from a realistic point of view, a "person" once entered the society, its idcode should not be changed, if it is to change, it is equivalent to another person. Therefore, we should only implement the read-only property of the Idcode. Similarly, the GetHashCode method should generate hashcode based on those properties or attributes that are read-only.

Another problem with the GetHashCode method is that it will always return only one integer type, while the capacity of an integral type obviously does not satisfy the capacity of the string, and the following example can produce two identical hashcode.

    string " NB0903100006 " ;       string " NB0904140001 " ;      Console.WriteLine (str1. GetHashCode ());      

To reduce the chance of generating the same hashcode between the two different types based on the string, a slightly improved version of the GetHashCode method is as follows:

     Public Override int GetHashCode ()      {          return"#" this. Idcode). GetHashCode ();      

Note that while overriding the Equals method, you should also implement a type-safe interface, iequatable, so the final version of the person type should be as follows:

    classPerson:iequatable<person>     {           Public stringIdcode {Get;Private Set; }  PublicPerson (stringIdcode) {               This. Idcode =Idcode; }                Public Override BOOLEquals (Objectobj) {              returnIdcode = = (obj asPerson ).          Idcode; }                Public Override intGetHashCode () {return(System.Reflection.MethodBase.GetCurrentMethod (). Declaringtype.fullname+"#"+ This. Idcode).          GetHashCode (); }                Public BOOLEquals (person other) {returnIdcode = =Other .          Idcode; }      }

Turn from: 157 recommendations for writing high-quality code to improve C # programs Minjia

157 recommendations for writing high-quality code to improve C # programs--recommendation 12: overriding equals When overriding GetHashCode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.