Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The = = operator in C #

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

= = operator and primitive type

We compare two integers in two ways, the first using the Equals (int) method, and each using the = = operator:

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}

Running the above example, the result of both statements is true. We decompiled through the ildasm.exe tool and looked at the IL code to see how it was executed at the bottom.

If you've never been exposed to IL instructions before, it doesn't matter, you don't need to understand all the instructions here, we just want to know the difference between the two comparisons.

You can see this line of code:

1 IL_0008: call instance bool [mscorlib] System.Int32::Equals (int32)

What is called here is the int type Equals (Int32) method (which is the implementation of the IEquatable interface).

Now let's take a look at the generated IL instructions using the = = operator comparison:

1 IL_0015: ceq

As you can see, the = = operator uses the ceq instruction, which uses the CPU register to compare two values. The underlying mechanism of the cantilever = operator is to use the ceq instruction to compare primitive types instead of calling the Equals method.

= = operator and reference type

Modify the sample code above to change the int type to a reference type, and then decompile and view the IL code through the ildasm.exe tool.

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 for the above C# code is as follows:

We see p1.Equals (p2) code, which compares equality by calling the Object.Equals (Object) virtual method, which is to be expected; now let's look at the IL code generated by the = = operator, which is consistent with the primitive type and uses the ceq instruction.

The = = operator and the String type

Let's take a look at an example of the String type:

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've seen before, but this time we use variables of type String. We create a string and pay for the S1 variable, and in the next line of code we create a copy of the string and pay for another variable name S2.

Run the above code and output the result on the console as follows:

You can see that ReferenceEquals returns false, which means that the two variables are different instances, but both the = = operator and the Equals method return true. In the String type, the = = operator executes the same results as Equals does.

Similarly, we have used the ildasm.exe tool to decompile and view the generated IL code.

We don't see the ceq instruction here. When you use the = = operator on the String type to determine equality, you're calling a new method of op_equality (string,string), which requires two parameters of type String, so what is it?

The answer is that the String type provides overloading of the = = operator. In C #, when we define a type, we can overload the = = operator of that type; for example, for the Person class we implemented in the previous example, if we overloaded the = = operator for it, the approximate code would be as follows:

1 public class Person 2 {3 4 public string Name {get; set;} 56 public static bool operator = = (Person p1, Person p2) 7 {8 / / Note that = = cannot be used here, otherwise it will result in 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.nameswitting 16} 17 18 public static bool operator! = (Person p1, Person p2) 19 {20 return! (P1 = = p2); 21} 22}

The above code is simple, we implement the = = operator overloading, which is a static method, but note here that the name of the method is perator = =, which is similar to static methods; in fact, they will be compiled into a special static method named op_Equality ().

To make things clearer, let's look at the String types implemented by Microsoft.

In the screenshot above, we can see that there are two operator overloads, one for equality and the other for inequality operators, which operate in exactly the same way, but negation equals operator output. It is important to note that if you want to overload the implementation of the = = operator of a type, you also need to overload it! The implementation of the = operator, otherwise compilation will report an error.

= = operator and value type

Before demonstrating the example of a value type, let's change the Person type from a reference type to a value type. 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}

Let's change the sample code 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 prompt, we need to overload the = = operator of the Person structure, which is as follows (ignoring the 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 adding the above code, recompile the program, view the IL code through the decompilation of the ildasm.exe tool, and find that the value type = = operator call is also the op_Equality method.

With regard to value types, we also need to explain that when the Equals (object) method is not overridden, the principle of this method is to traverse all fields through reflection and check the equality of each field, which we will not demonstrate; for value types, it is best to override the method.

= = operator and generics

Let's write another sample code that declares two variables of type String and compares operations 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 is as follows:

First, we use the ReferenceEquals method to determine that the two String variables have the same reference, then we use the instance method Equals (string), on the third line, we use the = = operator, and finally, we use the static method Object.quals (object,object) (which ends up calling the Object.Equals (object) method overridden by the String type). We come to the conclusion that:

The ReferenceEquals method returns false because they are not references to the same object

The Equals (string) method of type String also returns true because the two String types are the same (that is, the same sequence or character)

The = = operator will also return true because the values of the two String types are the same

The virtual method Object.Equals will also return true because the method is overridden in the String type to determine whether the String value is the same.

Now let's modify this code to change the String type to the Object 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 result of the operation is as follows:

The result returned by the third method is not consistent with that before modification, and the result returned by the = = operator is false. Why?

This is because the = = operator is actually a static method, and for a non-virtual method, it is decided which method to call at compile time. In the above example, the reference type uses the ceq instruction, while the String type call is a static op_Equality method; these two instances are not references to the same object, so the result of the ceq instruction execution is false.

Turning to the = = operator and generics, let's create a simple method to determine whether two generic parameters are equal and print the results on the console:

1 static void Equals (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 so simple that you cannot use the = = operator to compare two generic T. Because T can be any type, it can be a reference type, a value type, and cannot provide a concrete implementation of the = = operator.

If you modify the code like this:

1 static void Equals (T a, TB) where T: class2 {3 Console.WriteLine (a = = b); 4}

When we change the generic type T to a reference type, we can compile successfully; modify the code in the Main method to create two identical String types, 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 a, T b) where T: class12 {13 Console.WriteLine (a = = b); 14} 15}

The output is as follows:

The result is different from what you expected. The result we expect is true, and the output is false. However, if you think about it carefully, you may find the answer, because the constraints of generics are reference types, and the = = operator uses reference equality for reference types, as the IL code can prove:

If the = = operator in our generic method is changed to use the Equals method, the code is as follows:

1 static void Equals (T a, T b) 2 {3 Console.WriteLine (object.Equals (a, b)); 4}

If we switch to Equals, we can also remove the class constraint; if we run the code again, the console prints as we expected, because the call is implemented after the virtual method object.Equals (object) is rewritten.

But other problems come, if for the value type, there will be boxing, is there a solution? With regard to this point, we give a direct answer and have time to discuss this question.

Implement the IEquatable interface for the comparison value type, and change the comparison code to the following, so as to avoid boxing (for this, please refer to Lao Zhao's blog: http://blog.zhaojie.me/2013/04/dont-go-half-way-of-preventing-boxing.html):

1 static void Equals (T a, T b) 2 {3 Console.WriteLine (EqualityComparer.Default.Equals (a, b)); 4}

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report