C# difference between == and Equals()
When ==
is used on an expression of type object
, it'll resolve to System.Object.ReferenceEquals
.
Equals
is just a virtual
method and behaves as such, so the overridden version will be used (which, for string
type compares the contents).
What is the difference between == and Equals() for primitives in C#?
Short answer:
Equality is complicated.
Detailed answer:
Primitives types override the base object.Equals(object)
and return true if the boxed object
is of the same type and value. (Note that it will also work for nullable types; non-null nullable types always box to an instance of the underlying type.)
Since newAge
is a short
, its Equals(object)
method only returns true if you pass a boxed short with the same value. You're passing a boxed int
, so it returns false.
By contrast, the ==
operator is defined as taking two int
s (or short
s or long
s).
When you call it with an int
and a short
, the compiler will implicitly convert the short
to int
and compare the resulting int
s by value.
Other ways to make it work
Primitive types also have their own Equals()
method that accepts the same type.
If you write age.Equals(newAge)
, the compiler will select int.Equals(int)
as the best overload and implicitly convert short
to int
. It will then return true
, since this method simply compares the int
s directly.
short
also has a short.Equals(short)
method, but int
cannot be implicitly converted to short
, so you aren't calling it.
You could force it to call this method with a cast:
Console.WriteLine(newAge.Equals((short)age)); // true
This will call short.Equals(short)
directly, without boxing. If age
is larger than 32767, it will throw an overflow exception.
You could also call the short.Equals(object)
overload, but explicitly pass a boxed object so that it gets the same type:
Console.WriteLine(newAge.Equals((object)(short)age)); // true
Like the previous alternative, this will throw an overflow if it doesn't fit in a short
.
Unlike the previous solution, it will box the short
into an object, wasting time and memory.
Source Code:
Here are both Equals()
methods from the actual source code:
public override bool Equals(Object obj) {
if (!(obj is Int16)) {
return false;
}
return m_value == ((Int16)obj).m_value;
}
public bool Equals(Int16 obj)
{
return m_value == obj;
}
Further Reading:
See Eric Lippert.
Difference between == and Equals in C#
== is an operator, which, when not overloaded means "reference equality" for classes (and field-wise equality for structs), but which can be overloaded. A consequence of it being an overload rather than an override is that it is not polymorphic.
Equals is a virtual method; this makes it polymorphic, but means you need to be careful not to call it on null instances.
As a rule of thumb:
- if you know the type of something, and know it has an == overload (most core types such as string, int, float, etc have == meanings), then use ==
- if you don't know the type, Equals(a,b) may be recommended, as this avoids the null issue
- if you really want to check for the same instance (reference equality), consider using ReferenceEquals(a,b), as this will work even if the == is overloaded and Equals overridden
- when using generics, consider
EqualityComparer<T>.Default.Equals(a,b)
which avoids the null issue, supports Nullable-of-T, and supports IEquatable-of-T
What is the difference between .Equals and ==
From When should I use Equals and when should I use ==:
The Equals method is just a virtual
one defined in System.Object, and
overridden by whichever classes choose
to do so. The == operator is an
operator which can be overloaded by
classes, but which usually has
identity behaviour.For reference types where == has not
been overloaded, it compares whether
two references refer to the same
object - which is exactly what the
implementation of Equals does in
System.Object.Value types do not provide an overload
for == by default. However, most of
the value types provided by the
framework provide their own overload.
The default implementation of Equals
for a value type is provided by
ValueType, and uses reflection to make
the comparison, which makes it
significantly slower than a
type-specific implementation normally
would be. This implementation also
calls Equals on pairs of references
within the two values being compared.
using System;
public class Test
{
static void Main()
{
// Create two equal but distinct strings
string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
Console.WriteLine (a==b);
Console.WriteLine (a.Equals(b));
// Now let's see what happens with the same tests but
// with variables of type object
object c = a;
object d = b;
Console.WriteLine (c==d);
Console.WriteLine (c.Equals(d));
}
}
The result of this short sample program is
True
True
False
True
Difference between == operator and Equals() method in C#?
There are several things going on. Firstly, in this example:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
You claim that:
Both are different object reference.
That's not true due to string interning. s1
and s2
are references to the same object. The C# specification guarantees that - from section 2.4.4.5 of the C# 4 specification:
When two or more string literals that are equivalent according to the string equality operator (§7.10.7) appear in the same program, these string literals refer to the same string instance.
So in this particular case, you would still get "true" even if you printed object.ReferenceEquals(s1, s2)
, or if you made it use a true reference identity comparison with ==
:
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
However, even if these were references to separate objects, ==
is overloaded for string
. Overloading is a compile-time decision - the implementation to use depends on the compile-time types of the operands. So for example:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
Compare that with object.Equals(object)
which is a virtual method. As it happens, String
overloads this method as well, but importantly it overrides it. So if we change our code to:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
... then both method calls in the compiled code will simply be to object.Equals(object)
, but they'll still both print True because of polymorphism: the implementation in String
will be used.
Here's what a call to the overloaded method would look like:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)
Confusion about comparison by .Equals() vs. == operator and primitives vs. objects
In section 1 line 3
int a = 0;
short b = 0;
Console.WriteLine(a.Equals(b));
you call this overload of int
: bool Equals(int other)
, because b
(short) can be implicitly converted to int
so this overload is chosen. It returns true. In Section 3 line 3
int a = 0;
short b = 0;
object a1 = a;
object b1 = b;
Console.WriteLine(a1.Equals(b1)); //???
another overload of int
(not object
, because Equals
is virtual method) is called: bool Equals(object other)
. For it to return true other
should have exactly the same type (int
), but it's really short
so it returns false. Boxing is not relevant here, which you can verify with this:
int a = 0;
int c = 0;
object a1 = a;
object c1 = c;
// yes, different objects
Console.WriteLine(a1 == c1); // false
// still equal, because both are boxed ints
Console.WriteLine(a1.Equals(c1)); // true
As for understanding, I think documentation contains all relevant information. Just remember that:
Both
==
operator andEquals
method can be manually defined in class and so in theory can do anything. Your understanding relates only to "default" behavior.==
is not virtual in common sense, unlikeEquals
method. So when you doa1 == b1
-==
to be called in defined in compile time (based on types ofa1
andb1
), but when you calla1.Equals(b1)
- it is virtually dispatched so method to call is defined at runtime.
What is the difference between == and equals() in Java?
In general, the answer to your question is "yes", but...
.equals(...)
will only compare what it is written to compare, no more, no less.- If a class does not override the equals method, then it defaults to the
equals(Object o)
method of the closest parent class that has overridden this method. - If no parent classes have provided an override, then it defaults to the method from the ultimate parent class, Object, and so you're left with the
Object#equals(Object o)
method. Per the Object API this is the same as==
; that is, it returns true if and only if both variables refer to the same object, if their references are one and the same. Thus you will be testing for object equality and not functional equality. - Always remember to override
hashCode
if you overrideequals
so as not to "break the contract". As per the API, the result returned from thehashCode()
method for two objects must be the same if theirequals
methods show that they are equivalent. The converse is not necessarily true.
== or .Equals()
== is the identity test. It will return true if the two objects being tested are in fact the same object. Equals()
performs an equality test, and will return true if the two objects consider themselves equal.
Identity testing is faster, so you can use it when there's no need for more expensive equality tests. For example, comparing against null
or the empty string.
It's possible to overload either of these to provide different behavior -- like identity testing for Equals()
--, but for the sake of anybody reading your code, please don't.
Pointed out below: some types like String
or DateTime
provide overloads for the ==
operator that give it equality semantics. So the exact behavior will depend on the types of the objects you are comparing.
See also:
- http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx
Related Topics
How to Handle Both a Single Item and an Array For the Same Property Using Json.Net
Parsing CSV Files in C#, With Header
How to Use Linq to Select Object With Minimum or Maximum Property Value
Creating a Byte Array from a Stream
How to Pass Table Value Parameters to Stored Procedure from .Net Code
Listing All Permutations of a String/Integer
Create an Instance of a Class from a String
Better Way to Load 2 Dropdown in MVC
The Provider Is Not Compatible With the Version of Oracle Client
How to Add a Timeout to Console.Readline()
Case Insensitive 'Contains(String)'
How to Pass an Array into a SQL Server Stored Procedure
How to Match an Entire String With a Regex
Best Practice to Call Configureawait For All Server-Side Code