. 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 twoPerson
And contain the sameName
Attribute; obviously, the preceding twoPerson
Class 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 examplePerson
The two instances of the class have the same values, but they are separate instances and variables.p1
Andp2
The 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, ifPerson
The class does not have only one field and attribute, but has many attributes that you want to check.Person
If 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 identicalString
Type variable. Let's give variables firsts1
Pay the value, and then change the variables1
Copy the value and pay it to another variable.s2
, Run this code and print the output in the consoleTrue
, We can say twoString
Type variables are equal.
If"==
"The operator determines that the reference is equal. When the program is running, the console prints the output.False
, But usedString
Type"==
"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 variablenum1
Stored values and variablesnum2
Compare the stored values. However, if we modify this code and convert the two variablesObject
Type, 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 isFalse
Is opposite to the result of the previous code. This is becauseObject
The type is the reference type, so when we convert the integerObject
Type, 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 codeint
Convert type variables to interfacesICompareable<int>;
This is an interface provided by the. Net Framework,int
Type 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,String
Type 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? FortunatelyString
Type providesEquals
For 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,float
The 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:False
Note 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, althoughnum2
ConvertString
Type, the output result in the console is 0.7,num2
The 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.Animal
Indicates an animal, derived classDog
To represent a dog.
1 public class Animal2 {3 4 }5 6 public class Dog : Animal7 {8 9 }
If we wantAnimal
Class to realize whether the current instance is equal to otherAnimal
Instance, you may need to implement the interfaceIEquatable<Animal>
. This requires that it defineEquals()
Method andAnimal
Type 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 wantDog
Class also realizes whether the current instance is equal to otherDog
Instance, you may need to implement the interfaceIEquatable<Dog>
, Which means that it also definesEquals()
Method andDog
Type 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 thinkDog
Class will overwriteAnimal
ClassEquals()
Method, but the trouble isDog
OfEquals()
Method andAnimal
ClassEquals()
The method uses different parameter types and cannot be rewritten.Animal
ClassEquals()
Method. If you are not careful enough, you may callEquals
Method.
The usual solution is to rewriteObject
TypeEquals
Method.Object
Type 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