First look at the comparison between basic value types in the CLR, first look at the code:
int age1 = 30; int age2 = 30; Console.WriteLine("int == int: {0}", age1 == age2); Console.WriteLine("int == int: {0}", age2 == age1); Console.WriteLine("int Equals int: {0}", age1.Equals(age2)); Console.WriteLine("int Equals int: {0}", age2.Equals(age1)); Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age1, age2)); Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age2, age1)); Console.ReadLine();
Running results:
For the same basic value type (both int in the above example code), == and Equals() The comparison results are the same; since ReferenceEquals() determines whether the references of two objects are equal, for value types, because a boxing operation must be performed before each judgment, that is, a temporary object is generated each time, so it will never Return false. Next, I change the type of age2 in the code to byte type. What will happen to the comparison results? Please look at the running results:
Now we find that the results of age1.Equals(age2) and age2.Equals(age1) are different. In the comparison of basic value types, == compares the content of "value". If the "value" of two objects is the same, then the two objects are "=="; but Equals() does a little more. One point, there is actually an "implicit conversion" process in Equal(), which means that age1.Equals(age2) in the above code is equivalent to int.Equals(int), and byte data can be implicitly converted to Int type data, so the result of age1.Equals(age2) is true; and age2.Equals(age1) is equivalent to byte.Equals(byte), but int type data cannot be implicitly converted to byte type because there is a possibility of loss of data precision. . In fact, the Equals() of age2.Equals(age1) should be similar to the following code:
public override bool Equals(object obj) { if (!(obj is Byte)) { return false; } return m_value == ((Byte)obj).m_value; }
If it is an explicit conversion, the result of age2.Equals((byte)age1) will be true at this time.
Let’s talk about the comparison between string types. String is a special reference type because it is "immutable". Let’s look at the code first:
string name1 = "Jack"; string name2 = "Jack"; object o1 = name1; object o2 = name2; Console.WriteLine("name1 == name2: {0}", name1 == name2); Console.WriteLine("name1 Equals name2: {0}", name1.Equals(name2)); Console.WriteLine("o1 == o2: {0}", o1 == o2); Console.WriteLine("o1 Equals o2: {0}", o1.Equals(o2)); Console.WriteLine("o1 == name2: {0}", o1 == name2); Console.WriteLine("o1 Equals name2: {0}", o1.Equals(name2)); Console.WriteLine("name1 ReferenceEquals name2: {0}", object.ReferenceEquals(name1, name2)); Console.WriteLine("o1 ReferenceEquals o2: {0}", object.ReferenceEquals(o1, o2)); Console.ReadLine();
The results of the above code execution:
The comparison results are all true, now we will explain them one by one. Some people will say that name1 and name2 both store "Jack", so name1 and name2 are actually the same object, so the comparison results of name1==name2 and name1.Equals(name2) are the same; maybe you are right. When we view the source code of string through the .NET Reflector tool, we will see this piece of code:
operator == actually returns Equals(). So for the explanation of why the comparison results of name1==name2 and name1.Equals(name2) are the same, I think this explanation is more intuitive than "name1 and name2 are actually the same object".
We know that due to the particularity of the string type, the CLR can share multiple identical string contents through a string object, so the above name1 and name2 point to the same place, and the following o1 == o2, o1 == The comparison results of name2 and object.ReferenceEquals(name1, name2) are all true, which also verifies this statement (in fact, object.ReferenceEquals(name1, o2) is also true). However, what if the assignment of name1 and name2 becomes like this?
string name1 = new string(new char[] { 'J', 'a', 'c', 'k' }); string name2 = new string(new char[] { 'J', 'a', 'c', 'k' });
Look at the running results:
The comparison results of name1==name2 and name1.Equals(name2) are as easy to understand. As mentioned above, operator== actually returns Equals() (for For reference types, Equals() compares the contents stored on the managed heap), so the results are the same. But when comparing object objects o1 and o2, the results of o1 == o2 and o1.Equals(o2) are different. == of object objects compares type object pointers. o1 and o2 are two objects, and their type object pointers must be different; Equals() compares the contents of o1 and o2 stored on the managed heap, so o1.Equals (o2) is true. This also shows that the following o1 == name2 is false and o1.Equals(name2) is true.
Let’s take a look at the internal code of object.ReferenceEquals first:
Now it should be easy to understand that the results of object.ReferenceEquals(name1, name2) and object.ReferenceEquals(o1, o2) are both false. In fact, they are two == problem of object!
Finally, let’s talk about the comparison of custom reference types.
class MyName { private string _id; public string Id { get { return _id; } set { _id = value; } } public MyName(string id) { this.Id = id; } }
Change the above declarations of name1 and name2 to:
MyName name1 = new MyName("12"); MyName name2 = new MyName("12");
Others remain unchanged, and the running result is:
name1 and name2 are two completely different objects. It should be easy to understand that the comparison results are all false.
For more related articles on understanding the differences between ==, Equals() and ReferenceEquals() in C# at once, please pay attention to the PHP Chinese website!