What is the difference between a==b and a.Equals(b) in the context of value and reference types?
I've come across this question quite a few times, and while the answers make sense, i wanted to check it out myself with a simple console app.
class Program
{
static void Main(string[] args)
{
// Case 1 : FOR REFERENCE TYPES where class b is a copy of class a
Class1 a = new Class1("Hello");
Class1 b = a;
Console.WriteLine("case 1");
Console.WriteLine(a.GetHashCode());
Console.WriteLine(b.GetHashCode());
Console.WriteLine(a==b); //true
Console.WriteLine(a.Equals(b)); //true
// Case 2 : FOR REFERENCE TYPES where class b is not a copy of class a, but it assigned the same values
// Though the referenced memory addresses are different, the fields of the class are assigned the same values, but will have different hashcodes and are therfore not equal.
Class1 c = new Class1("Hello");
Console.WriteLine(" ");
Console.WriteLine("case 2");
Console.WriteLine(a.GetHashCode());
Console.WriteLine(c.GetHashCode());
Console.WriteLine(a==c);//false
Console.WriteLine(a.Equals(c));//false
// Case 3 : FOR REFERENCE TYPES where two strings are assigned the same values, an exception to the way value types behave.
// using the '==' operstor with strings compares their values not memory addresses.
string s1 = "hi";
string s2 = "hi";
Console.WriteLine(" ");
Console.WriteLine("case 3");
Console.WriteLine(s1 == s2);//true
Console.WriteLine(s1.Equals(s2));//true
//Case 4 : FOR VALUE TYPES - they are the same when comparing the same type.
int x = 5;
int y = 5;
Console.WriteLine(" ");
Console.WriteLine("case 4");
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(x == y);//true
Console.WriteLine(x.Equals(y));//true
// Case 5 : Another value type scenario for completeness
x = y;
Console.WriteLine(" ");
Console.WriteLine("case 5");
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(x.GetType());
Console.WriteLine(y.GetType());
Console.WriteLine(x == y);//true
Console.WriteLine(x.Equals(y));//true
// Case 6 : Yet Another value type scenario for completeness, with different value types.
float z = 5;
Console.WriteLine(" ");
Console.WriteLine("case 6");
Console.WriteLine(x.GetType());
Console.WriteLine(z.GetType());
Console.WriteLine(x);
Console.WriteLine(z);
Console.WriteLine(x == z);//true
Console.WriteLine(x.Equals(z));//false, as the values being compared are of two different types- int and float. The .Equals method expects them to be the same type.
// Case 7 : For giggles, Yet Another ref type scenario for completeness, with objects.
string s3 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' 开发者_JS百科});
string s4 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
object obj1 = s3;
object obj2 = s4;
Console.WriteLine(" ");
Console.WriteLine("case 7");
Console.WriteLine(obj1.ToString());
Console.WriteLine(obj2.ToString());
Console.WriteLine(obj1.GetHashCode());
Console.WriteLine(obj2.GetHashCode());
Console.WriteLine(obj1 == obj2);//false - as they refer to different addresses.
Console.WriteLine(obj1.Equals(obj2));//true - in this case both objects have the same hashcode.
Console.ReadKey();
}
public class Class1
{
string name;
public Class1(string strName)
{
name = strName;
}
}
}
Assumption 1 : What i understood from the commonly posted replies was that for reference types, a==b compares references , whereas a.Equals(b) compares the actual values referenced. This is what threw me off when viewing the results of my program.
With reference to my program, In Case 2 - Though the referenced memory addresses for a and c are different, their fields are assigned the same values. Still a.Equals(c) returns false as they still are not equal as they have different hashcodes. I had assumed they would return true initially based on Assumption 1, but it makes sense they are not equal. But then what really is the exact difference between == and .Equals?
In case 3 , using the '==' operator with strings compares their values not memory addresses.
In case 6, the value types being compared by the .Equals method are different, whereas the method expects them to be of the same type. Hence it returns false.
What I still don't understand is case 7. Why do the objects have the same hashcode in this case? Sorry for the lengthy code and thanks in advance!
I think a key thing to remember is that with a == b
the compiler determines what function to call at compile-time by looking at the types of a
and b
. If a
and b
are both of type object
, the compiler will generate a call to ReferenceEquals
, whereas if they are both of type string
the compiler will generate a call to string.Equals
.
When the compiler sees a.Equals(b)
, however, it generates a call to the a
's Equals
method, which is determined at runtime because it's a virtual method. If a
is a string then it will call the overload that does a string comparison (as you expect). If a
is some other object then it will call the overloaded Equals
method on that object if it has one, or object.Equals
(which does a ReferenceEquals
comparison) if it doesn't.
a.Equals(b)
will only do what you've written code for. It's just a virtual method call.
The default behaviour (for reference types) is to just compare references.
How are you implementing Equals() in Class1? If you don't provide a method to override Equals it'll use the default Equals method which will just compare the reference values.
a.equals is the method present in the java.lang.Object class which compares the references of the object passed to it with object on which it was called.
== is a operator to check again the references.
b. Since equals is method in Object class it can be overridden and can be used to do anything, either to compare values inside the objects, compare references or calculate hash codes and compare them. So incase of String class the equals method have been overidden to compare the values of the objects passed to it.
精彩评论