. Net equality

Source: Internet
Author: User

. Net equality

In the. Net Framework, If you view all types of base classes: System. Object classes, you will find the following four methods for equal judgment:

  • Static Equals ()
  • Virtual Equals ()
  • Static ReferenceEquals ()
  • Virtual GetHashCode ()

In addition, Microsoft has provided nine different interfaces for comparison:

  • IEquatable <T>
  • IComparable
  • IComparable <T>
  • IComparer
  • IComparer <T>
  • IEqualityComparer
  • IEqualityComparer <T>
  • IStructuralEquatable
  • IStructuralComparable

Do you really understand these methods and interfaces? Improper use may cause fatal errors and damage the set dependent on these interfaces.

In the next few articles, we will discuss these methods and interfaces, focusing on how to correctly use these methods and interfaces.

 

Equal

The following four reasons may impede us from understanding how equal comparison is executed:

 

The reference is equal to the value.

As we all know. in the. Net Framework, the reference types do not contain actual values during storage. They contain a pointer pointing to the locations where actual values are stored in the memory, which means that for the reference type, there are two ways to measure equality. Both variables point to the same location in the memory, which we call equal references or the same object; the positions specified by the two variables include the same values. Even if they point to different locations in the memory, we call them equal values.

The following example can be used to describe the above points:

 1 class Program 2 {  3     static void Main(String[] args) 4     { 5         Person p1 = new Person(); 6         p1.Name = "Sweet"; 7   8         Person p2 = new Person(); 9         p2.Name = "Sweet";10  11         Console.WriteLine(p1 == p2);12     }  13 }

We instantiate twoPersonAnd contain the sameNameAttribute; obviously, the preceding twoPersonClass instances are the same, they contain the same value, but when running the sample code, the console prints the output isFalse, Which means they are not equal.

This is because in the. Net Framework, the default judgment method for the reference type is that the reference is equal, in other words ,"==The "operator determines whether the two variables point to the same location in the memory. Therefore, in this examplePersonThe two instances of the class have the same values, but they are separate instances and variables.p1Andp2The two are memory locations.

  The execution speed of equal references is very fast, because you only need to check whether the two variables point to the same address in the memory, and the execution speed is slower when the values are equal.For example, ifPersonThe class does not have only one field and attribute, but has many attributes that you want to check.PersonIf the two instances of the class have the same value, you must check each field or attribute. C # does not provide operators to check whether the values of two types of instances are equal. If you want to implement this function for some reason, you need to write your own code to do this.

Now let's look at another example:

 1 class Program 2 {  3     static void Main(String[] args) 4     { 5         string s1 = "Sweet"; 6   7         string s2 = string.Copy(s1); 8   9         Console.WriteLine(s1 == s2);10      } 11  }

 

The above code is very similar to the previous sample code, but in this example, we use"=="Operator determines two identicalStringType variable. Let's give variables firsts1Pay the value, and then change the variables1Copy the value and pay it to another variable.s2, Run this code and print the output in the consoleTrue, We can say twoStringType variables are equal.

If"=="The operator determines that the reference is equal. When the program is running, the console prints the output.False, But usedStringType"=="The operator determines equal values.

 

Reference equal to Value Type

The problem of referencing equal values is only applicable to reference types. For unboxed value types, such as integers and floating point types, the actual values are included in variable storage, it means that equal is the comparison value.

The following code compares two integers, the two are equal, because"=="Operator will compare the actual value of the variable.

 1 class Program 2 { 3      static void Main(String[] args) 4     { 5         int num1 = 2; 6   7         int num2 = 2; 8   9         Console.WriteLine(num1 == num2);10     } 11 }

In the above Code ,"=="The operator is to convert the variablenum1Stored values and variablesnum2Compare the stored values. However, if we modify this code and convert the two variablesObjectType, the Code is as follows:

1 int num1 = 2;2  3 int num2 = 2;4  5 Console.WriteLine((object)num1 == (object)num2);

Run the sample code. The result isFalseIs opposite to the result of the previous code. This is becauseObjectThe type is the reference type, so when we convert the integerObjectType, which is actually two different reference instances after the two integers are boxed ,"=="The runtime compares the references of two objects, not the values.

It seems that the above example is rare, because we usually do not convert the value type to the reference type, but there is another common case, we need to convert the value type to the interface.

1 Console.WriteLine((IComparable<int>)num1 == (IComparable<int>)num2); 

To illustrate this situation, we modify the sample codeintConvert type variables to interfacesICompareable<int>;This is an interface provided by the. Net Framework,intType to implement this interface (we will discuss this interface in other blogs ).

In the. Net Framework, the interface is actually a reference type. If we run this code, the returned result isFalse.Therefore, when you convert a value type to an interface, you must be very careful. If you perform the equality check, the returned results compare the references that are equal.

 

"=" Operator

If C # provides different operators to determine the same value type and reference type respectively, these codes may not be a problem, but C # only provides one"=="Operator, there is no display method to tell the operator What type is actually determined. For example, the following line of code:

1 Console.WriteLine(var1 == var2)

We do not know whether the above "=" operator uses equal references or equal values, because we need to know"=="The Running calculation determines the type. In fact, C # is also designed in this way.

In the above content, we will introduce in detail"=="The Role and Judgment Method of operators. After reading this blog, I hope you can learn more about the use of operators than other developers"=="What happened when determining the condition, you can also learn more about how the two objects are judged to be equal.

 

Multiple methods for determining equal values

There is another problem when the complex values are equal. There are usually multiple methods to compare the values of the specified type,StringType is the best example.

In this case, you may need to ignore the case sensitivity when comparing strings. For example, if you search for an item with an English name on an e-commerce platform, we need to ignore the case sensitivity. Fortunately, this comparison method is used by default in the SQL Server database. is there a way to meet our requirements in the. Net Framework? FortunatelyStringType providesEqualsFor more information, see the following example:

1 string s1 = "SWEET";2 3 string s2 = "sweet";4 5 Console.WriteLine(s1.Equals(s2,StringComparison.OrdinalIgnoreCase));

Run the preceding example in the program and print the output on the consoleTrue.

Of course, the. Net Framework also provides multiple methods to determine whether the type value is equal. The most common method, the type can be implemented throughIEquatable<T>The default value of the interface definition type is equal. If you do not want to redefine your type, the. Net Framework also provides another mechanism for implementation.IEqualityComparer<T>The interface defines a comparator to determine whether two instances of the same type are equal. For example, if you want to ignore spaces in the String type for comparison, you can define a comparator to implement this function.
. Net also provides an interfaceICompareable<T>To determine whether the current type is greater than or less than the comparison, you can also useIComparer<T>Interface to implement a comparison tool. These interfaces are generally used in object sorting.

 

Accuracy of Floating Point Numbers

If you use floating point numbers in the. Net Framework, unexpected problems may occur. Let's look at an example:

1 float num1 = 2.000000f;2 float num2 = 2.000001f;3 4 Console.WriteLine(num1 == num2);

We have two almost identical floating-point numbers, but obviously they are different, because they have different numbers at the end. We run the program and the console prints the outputTrue.

From the procedural perspective, they are equal, which is in conflict with our expected results. However, you may have guessed where the problem is. There is a precision problem with the number type,floatThe data type cannot store enough valid numbers to distinguish these two numbers, and it still has other computing problems. Let's look at this example:

1 float num1 = 0.7f;2 float num2 = 0.6f + 0.1f;3 4 Console.WriteLine(num2);5 Console.WriteLine(num1 == num2);

This is a simple calculation. We add 0.6 and 0.1. Obviously, the result after adding is 0.7. However, when we run the program, the console prints the output as follows:FalseNote that the result is False, indicating that the calculation result is not equal to 0.7. The reason is that the rounding error occurs during the floating point operation, which leads to the storage of a very close number, althoughnum2ConvertStringType, the output result in the console is 0.7,num2The value is not equal to 0.7.

  

Rounding Errors mean that determining equality usually gives you an incorrect result. the. Net Framework does not provide a solution. We recommend that you do not try to compare whether floating point numbers are equal, because it may not be the expected result. This problem only affects equal-to-comparison. Generally, it does not affect comparison between less-than-and greater-than. In most cases, comparing a floating point number greater than or less than another floating point number does not cause this problem.

Stackoverflow provides such a solution for your reference.

 

Conflict between equal value and object-oriented

This problem may be surprising to experienced developers. In fact, it is a conflict between comparison, type security, and good object-oriented practices. If these three problems are not properly handled, other bugs may occur.

Let's take an example. Suppose we have a base class.AnimalIndicates an animal, derived classDogTo represent a dog.

1 public class Animal2 {3 4 }5 6 public class Dog : Animal7 {8 9 }

If we wantAnimalClass to realize whether the current instance is equal to otherAnimalInstance, you may need to implement the interfaceIEquatable<Animal>. This requires that it defineEquals()Method andAnimalType instance as a parameter.

1 public class Animal : IEquatable<animal>2 {3     public virtual bool Equals(Animal other)4     {5         throw new NotImplementedException();6     }7 }

If we wantDogClass also realizes whether the current instance is equal to otherDogInstance, you may need to implement the interfaceIEquatable<Dog>, Which means that it also definesEquals()Method andDogType instance as a parameter.

1 public class Dog : Animal, IEquatable<Dog>2 {3     public virtual bool Equals(Dog other)4     {5         throw new NotImplementedException();6     }7 }

Now the problem arises. In this well-designed OOP code, you may thinkDogClass will overwriteAnimalClassEquals()Method, but the trouble isDogOfEquals()Method andAnimalClassEquals()The method uses different parameter types and cannot be rewritten.AnimalClassEquals()Method. If you are not careful enough, you may callEqualsMethod.

The usual solution is to rewriteObjectTypeEqualsMethod.ObjectType is the parameter type, which means it is not type safe, but it can override the method of the base class normally, and this is also the simplest solution.

 

Summary
  • C # syntactically, non-partition values are equal and references are equal, which means it is sometimes difficult to predict under certain circumstances"=="How operators are executed;
  • There are multiple methods to achieve equal value determination. the. Net framework allows the type to define the default value comparison method, and provides a self-compiled comparator mechanism to achieve value comparison for each type;
  • We do not recommend that you use floating point numbers for Equal Value Comparison, Because rounding errors may cause the results to exceed expectations;
  • There is a conflict between equal values, type security, and good object-oriented.

 

Reprint please indicate from, original link: http://www.cnblogs.com/tdfblog/p/Story-of-Equality-in-NET-Part1.html

 

Related Article

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.