C # medium = Operator,
In this blog, we will introduce the following content:
- = Operator and primitive type
- = Operator and reference type
- = Operator and String type
- = Operator and Value Type
- = Operators and generics
= Operator and primitive type
We use two methods to compare two integers. The first one isEquals(int)
The = Operator is used for each of the two methods:
1 class Program 2 { 3 static void Main(String[] args) 4 { 5 int num1 = 5; 6 int num2 = 5; 7 8 Console.WriteLine(num1.Equals(num2)); 9 Console.WriteLine(num1 == num2);10 }11 }
Run the preceding example.true
. We use the ildasm.exe tool to decompile the code, view the IL code, and understand how the underlying layer is executed.
If you have never been in touch with the IL command before, but it doesn't matter, you don't need to understand all the commands here. We just want to know the differences between the two comparison methods.
You can see this line of code:
1 IL_0008: call instance bool [mscorlib]System.Int32::Equals(int32)
What is called here isint
TypeEquals(Int32)
Method (this method isIEquatable<Int>
Interface implementation ).
Now let's take a look at the IL commands generated by comparison using the = Operator:
1 IL_0015: ceq
As you can see, = The runtime isceq
Command, which uses the CPU register to compare two values. C #== the underlying mechanism of operators is to useceq
Command, instead of callingEquals
Method.
= Operator and reference type
Modify the sample code above and setint
After compilation, the ildasm.exe tool is used to decompile and view the IL code.
1 class Program 2 { 3 static void Main(String[] args) 4 { 5 Person p1 = new Person(); 6 p1.Name = "Person1"; 7 8 Person p2 = new Person(); 9 p2.Name = "Person1";10 11 Console.WriteLine(p1.Equals(p2));12 Console.WriteLine(p1 == p2);13 }14 }
The IL code of the above C # code is as follows:
We can see thatp1.Equals(p2)
Code, which is calledObject.Equals(Object)
It is expected that the virtual methods are equal. Now let's look at the IL code generated by the = Operator, which is consistent with the primitive type and usesceq
Command.
= Operator and String type
Take a lookString
Type example:
1 class Program 2 { 3 static void Main(String[] args) 4 { 5 string s1 = "Sweet"; 6 string s2 = String.Copy(s1); 7 8 Console.WriteLine(ReferenceEquals(s1, s2)); 9 Console.WriteLine(s1 == s2);10 Console.WriteLine(s1.Equals(s2));11 }12 }
The above code is very similar to what we have seen before, but this time we useString
Type variable. We create a string and pay its1
Variable. In the next line of code, we create a copy of this string and pay it to another variable name.s2
.
Run the above Code. The output result on the console is as follows:
You can seeReferenceEquals
Returnfalse
, Which means the two variables are different instances, but the = Operator andEquals
Method returns true. InString
Type, = the result of the operator execution andEquals
The execution results are the same.
Similarly, we used the ildasm.exe tool to decompile and view the generated IL code.
We do not seeceq
CommandString
When the = Operator is used to determine equality,op_equality(string,string)
The new method, which requires twoString
Type parameter, so what is it?
The answer is:String
Type provides the = Operator overload. In C #, when we define a type, we can reload the = Operator of this type. For example, forPerson
Class. If we reload the = Operator for it, the approximate code is as follows:
1 public class Person 2 {3 4 public string Name {get; set;} 5 6 public static bool operator = (Person p1, Person p2) 7 {8 // note = cannot be used here, otherwise StackOverflowException 9 if (ReferenceEquals (p1, p2) 10 return true; 11 12 if (ReferenceEquals (p1, null) | ReferenceEquals (p2, null) 13 return false; 14 15 return p1.Name = p2.Name; 16} 17 18 public static bool operator! = (Person p1, Person p2) 19 {20 return! (P1 = p2); 21} 22}
The above code is very simple. We implemented the = Operator overload. This is a static method, but note that the method name isperator ==
Is similar to static methods. In fact, they are named by the compilerop_Equality()
.
To make it clearer, let's look at what Microsoft has implementedString
Type.
In the above, we can see that there are two operators that are reloaded. One is used for equality, and the other is an inequality operator. The operation method is identical, but the negative is equal to the operator output. Note that if you want to reload the implementation of a type = Operator, You need to reload it! = Operator implementation. Otherwise, an error will be reported during compilation.
= Operator and Value Type
Before demonstrating the value type example, we first change the Person type from the reference type to the value type. The Person is defined as follows:
1 public struct Person 2 { 3 public string Name { get; set; } 4 5 public Person(string name) 6 { 7 Name = name; 8 } 9 10 public override string ToString()11 {12 13 return Name;14 }15 }
The sample code is changed to the following:
1 class Program 2 { 3 static void Main(String[] args) 4 { 5 Person p1 = new Person("Person1"); 6 Person p2 = new Person("Person2"); 7 8 Console.WriteLine(p1.Equals(p2)); 9 Console.WriteLine(p1 == p2);10 }11 }
When we try to compile the above Code, VS will prompt the following error:
According to the error message, we need to implement the = Operator overload of the Person struct. The overloaded statements are as follows (ignore specific logic ):
1 public static bool operator ==(Person p1, Person p2)2 {3 }4 public static bool operator !=(Person p1, Person p2)5 {6 }
After the merge worker code, recompile the program and decompile the ildasm.exe tool to check the IL code. The value type = operator is also called.op_Equality
Method.
For the value type, we also need to describe a problem without rewriting.Equals(object)
The principle of this method is to traverse all fields through reflection and check the equality of each field. We will not demonstrate this. For the value type, we recommend that you override this method.
= Operators and generics
Let's write another sample code and declare twoString
Type variables are compared in four different ways:
1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 string str = "Sweet"; 6 string str1 = string.Copy(str); 7 8 Console.WriteLine(ReferenceEquals(str, str1)); 9 Console.WriteLine(str.Equals(str1));10 Console.WriteLine(str == str1);11 Console.WriteLine(object.Equals(str, str1));12 }13 }
The output result is as follows:
First, we useReferenceEquals
Method judgmentString
The variables are referenced in the same way. Next we will use the instance method.Equals(string)
In the third line, we use the = Operator. Finally, we use the static method.Object.quals(object,object)
(The method is finally calledString
Type overrideObject.Equals(object)
Method ). We can conclude that:
ReferenceEquals
Method returnfalse
Because they are not referenced by the same object;
String
TypeEquals(string)
Method return is alsotrue
Because twoString
The type is the same (that is, the same sequence or character );
- = The operator will also return
true
Because the twoString
Values of the same type;
- Virtual Method
Object.Equals
Will also returntrue
This is becauseString
Type override method, which determinesString
Whether the value is the same.
Now let's modify this code and setString
Type changedObject
Type:
1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 object str = "Sweet"; 6 object str1 = string.Copy((string)str); 7 8 Console.WriteLine(ReferenceEquals(str, str1)); 9 Console.WriteLine(str.Equals(str1));10 Console.WriteLine(str == str1);11 Console.WriteLine(object.Equals(str, str1));12 }13 }
The running result is as follows:
The result returned by the third method is inconsistent with that returned before modification. = The result returned by the operator isfalse
Why?
This is because the = Operator is actually a static method. For a non-virtual method, the method called is determined during compilation. In the preceding example, the reference type isceq
Command, andString
Type call is staticop_Equality
Method; the two instances are not referenced by the same object, soceq
The command execution result isfalse
.
Let's talk about the = Operator and generics. We create a simple method to determine whether two generic parameters are equal and print the result on the console:
1 static void Equals<T>(T a, T b)2 {3 Console.WriteLine(a == b);4 }
But when we compile this code, VS prompts the following error:
The error shown above is very simple. You cannot use the = Operator to compare two generic T types. Because T can be of any type, it can be a reference type, value type, and cannot provide a specific implementation of the = Operator.
Modify the Code as follows:
1 static void Equals<T>(T a, T b) where T : class2 {3 Console.WriteLine(a == b);4 }
When we change generic type T to reference type, compilation can be successful; ModificationMain
Method to create two identicalString
Type, as in the previous example:
1 public class Program 2 { 3 static void Main(string[] args) 4 { 5 string str = "Sweet"; 6 string str1 = string.Copy(str); 7 8 Equals(str, str1); 9 }10 11 static void Equals<T>(T a, T b) where T : class12 {13 Console.WriteLine(a == b);14 }15 }
The output result is as follows:
The results are different from what you expected. What we expect istrue
, The output result isfalse
. However, if you think about it carefully, you may find the answer, because the generic constraint is the reference type, and the = Operator is equivalent to the reference type. The IL code can prove this:
If the = operator in the generic method is changed to useEquals
The Code is as follows:
1 static void Equals<T>(T a, T b)2 {3 Console.WriteLine(object.Equals(a, b));4 }
We useEquals
, You can also removeclass
Constraint; if we run the code again, the result printed on the console is the same as we expected, because the call is a virtual method.object.Equals(object)
After rewriting.
However, there are other problems. If the value type is used, packing is generated here. Is there a solution? We will give a direct answer to this question and have time to discuss it.
Implement the comparison value typeIEquatable<T>
Interface, and change the comparison code to the following to avoid packing:
1 static void Equals<T>(T a, T b)2 {3 Console.WriteLine(EqualityComparer<T>.Default.Equals(a, b));4 }
Summary
The underlying mechanism of the primitive type = Operator isceq
Command, which is compared by CPU registers;
For the quote type = Operator, it also usesceq
Command to compare the memory address;
For the type of the overload = Operator, what is actually called isop_equality
This special method;
Always = Operator overload andObject.Equals(Object)
The Write result of the virtual method returns the same result;
For the value type,Equals
By default, the method traverses all fields through reflection and checks the equality of each field. To improve performance, we need to override this method;
By default, the = Operator cannot be used for value types, and the = operator must be overloaded;
Since the = Operator overload implementation is actually a static method, it may be different from the actual results when used in generic classes or methods.Equals
This problem can be avoided.
Reprint please indicate from, original link: http://www.cnblogs.com/tdfblog/p/About-Equality-Operator-in-NET.html