C# .Equals(), .Referenceequals() and == Operator

C# .Equals(), .ReferenceEquals() and == operator

The source of your confusion appears to be that there is a typo in the extract from C# station, which should read: "... except that the Equals works only on object instances. The ReferenceEquals method is static."


You are loosely correct about the differences in the semantic meanings of each (although "different instances of the same object" seems a little confused, it should probably read "different instances of the same type) and about which can be overridden.

If we leave that aside, let's deal with the last bit of your question, i.e. how they work with plainSystem.Objectinstances and System.Objectreferences (we need both to dodge the non-polymorphic nature of ==). Here, all three operations will work equivalentally, but with a caveat:Equalscannot be invoked onnull.

Equalsis an instance method that takes one parameter (which can benull). Since it is an instance method (must be invoked on an actual object), it can't be invoked on a null-reference.

ReferenceEquals is a static method that takes two parameters, either / both of which can be null. Since it is static (not associated with an object instance), it will not throw aNullReferenceException under any circumstances.

==is an operator, that, in this case (object), behaves identically to ReferenceEquals. It will not throw aNullReferenceExceptioneither.

To illustrate:

object o1 = null;
object o2 = new object();

//Technically, these should read object.ReferenceEquals for clarity, but this is redundant.
ReferenceEquals(o1, o1); //true
ReferenceEquals(o1, o2); //false
ReferenceEquals(o2, o1); //false
ReferenceEquals(o2, o2); //true

o1.Equals(o1); //NullReferenceException
o1.Equals(o2); //NullReferenceException
o2.Equals(o1); //false
o2.Equals(o2); //true

Operator ==, Equal Method and Object.ReferenceEqual in C#

Please clear your mind from these statements:

Operator == It is used for check equal references.

Equal Method - It is used for check equal values.

Both operator== and Equals can be overridden to modify their behavior. Since operator== is not virtual it is known at compile time that which method is chosen but Equals is chosen at runtime base on object type. (The whole process of choosing appropriate method is called method resolution)

Line 1: True. Because string.operator== has chosen by compiler and it compares the strings not their references.

Line 2: False. Because int.Equals(object) is chosen by compiler and object(strValue) is a string not an int. int is not equal to string so it is false.

Line 3: True. Because string.Equals(string) is chosen by compiler and it checks equality of the values not references.

Line 4: False. Becuase object.ReferenceEquals checks for reference equality so the answer is obvious.

Line 5: False. Same as above. intValue.ToString() creates a new string object on memory with value of "5" and it is not the same object as strValue points to so the answer is false.

Why do the results of the Equals and ReferenceEquals methods differ even though variables are reference types?

obj and obj1 refer to 2 different objects, so object.ReferenceEquals() will return false.

Equals() returns true, because the compiler implements Equals() for anonymous types. It will return true if all the properties of both objects have the same values.

Why ReferenceEquals and == operator behave different from Equals

After I get childs from the session I Merge them with the session.

var childs = session.Query<Child>();
// Do some stuff
foreach (var child in childs)
{
session.Merge(child);
}

var parents = childs.Select(x => x.ParentEntity).ToList();

It appear that the merge detached the entity from the session and return a new Proxy attached to the session.

It can be fixed with

var newChild = (Child)session.Merge(child);
// Or:
session.Update(child); // (We have session.Clear() in our tests so I can't use this because it makes troubles when you update detached Entity

Should == operator behave exactly as Equals()?

MSDN is almost clear about it

To check for reference equality, use ReferenceEquals. To check for
value equality, you should generally use Equals
. However, Equals as it
is implemented by Object just performs a reference identity check. It
is therefore important, when you call Equals, to verify whether the
type overrides it to provide value equality semantics. When you create
your own types, you should override Equals.


By default, the operator == tests for reference equality by
determining if two references indicate the same object, so reference
types do not need to implement operator ==
in order to gain this
functionality. When a type is immutable, meaning the data contained in
the instance cannot be changed, overloading operator == to compare
value equality instead of reference equality can be useful
because, as
immutable objects, they can be considered the same as long as they
have the same value. Overriding operator == in non-immutable types is
not recommended
.

IEquatable documentation is also very clear

Defines a generalized method that a value type or class implements to
create a type-specific method for determining equality of instances.

Compare two objects by reference when equality operator is overridden

Operators can't be overridden - they can only be overloaded.

So the == operator in object.ReferenceEquals is still comparing references, or you could do the same thing yourself by casting one or both operands:

string x = "some value";
string y = new string(x.ToCharArray());
Console.WriteLine(x == y); // True
Console.WriteLine((object) x == (object) y); // False
Console.WriteLine(ReferenceEquals(x, y)); // False

object.ReferenceEquals or == operator?

There's no difference between the two. You're confusing overriding Equals (which isn't called in either implementation) with overloading == (which won't be relevant in either snippet as overloading is performed at compile time, and the compiler doesn't know enough about T to use any specific overload).

Just to show what I mean:

static void ThrowIfFoo<T>(this T argument, string name) where T : class
{
if (argument == "foo")
{
throw new Exception("You passed in foo!");
}
}

Testing with:

"foo".ThrowIfFoo(); // Throws

string x = "f";
x += "oo"; // Ensure it's actually a different reference

x.ThrowIfFoo(); // Doesn't throw

ThrowIfFoo doesn't know that T will be a string - because that depends on the calling code - and the overload resolution is only performed when ThrowIfFoo is compiled. Therefore it's using the operator ==(object, object) rather than ==(string, string).

In other words, it's like this:

object foo1 = "foo";

string tmp = "f";
object foo2 = tmp + "oo";

Console.WriteLine(foo1.Equals(foo2)); // Prints True
Console.WriteLine(foo1 == foo2); // Prints false
Console.WriteLine((string) foo1 == (string) foo2); // Prints True

In the last line, the compiler knows it can use the overload of == because both operands have compile-time types of string.

C# operator== : what is standard practice (reference/value equality)?


The question was whether it is commonly acceptable to override
operator== to test for value equality

It depends on the object, if the object is immutable then you can override == operator, otherwise not. (Remember they are just guidelines).

See: Guidelines for Overriding Equals() and Operator == (C# Programming Guide)

By default, the operator == tests for reference equality by
determining whether two references indicate the same object.
Therefore, reference types do not have to implement operator == in
order to gain this functionality. When a type is immutable, that
is, the data that is contained in the instance cannot be changed,
overloading operator == to compare value equality instead of reference equality can be useful because, as immutable objects, they
can be considered the same as long as they have the same value. It
is not a good idea to override operator == in non-immutable types.



Related Topics



Leave a reply



Submit