When can a == b be false and a.Equals(b) true? - c#

I ran into this situation today. I have an object which I'm testing for equality; the Create() method returns a subclass implementation of MyObject.
MyObject a = MyObject.Create();
MyObject b = MyObject.Create();
a == b; // is false
a.Equals(b); // is true
Note I have also over-ridden Equals() in the subclass implementation, which does a very basic check to see whether or not the passed-in object is null and is of the subclass's type. If both those conditions are met, the objects are deemed to be equal.
The other slightly odd thing is that my unit test suite does some tests similar to
Assert.AreEqual(MyObject.Create(), MyObject.Create()); // Green bar
and the expected result is observed. Therefore I guess that NUnit uses a.Equals(b) under the covers, rather than a == b as I had assumed.
Side note: I program in a mixture of .NET and Java, so I might be mixing up my expectations/assumptions here. I thought, however, that a == b worked more consistently in .NET than it did in Java where you often have to use equals() to test equality.
UPDATE Here's the implementation of Equals(), as requested:
public override bool Equals(object obj) {
return obj != null && obj is MyObjectSubclass;
}

The key difference between == and Equals is that == (like all operators) is not polymorphic, while Equals (like any virtual function) is.
By default, reference types will get identical results for == and Equals, because they both compare references. It's also certainly possible to code your operator logic and Equals logic entirely differently, though that seems nonsensical to do. The biggest gotcha comes when using the == (or any) operator at a higher level than the desired logic is declared (in other words, referencing the object as a parent class that either doesn't explicitly define the operator or defines it differently than the true class). In such cases the logic for the class that it's referenced as is used for operators, but the logic for Equals comes from whatever class the object actually is.
I want to state emphatically that, based solely upon the information in your question, there is absolutely no reason to think or assume that Equals compares values versus references. It's trivially easy to create such a class, but this is not a language specification.
Post-question-edit edit
Your implementation of Equals will return true for any non-null instance of your class. Though the syntax makes me think that you aren't, you may be confusing the is C# keyword (which confirms type) with the is keyword in VB.NET (which confirms referential equality). If that is indeed the case, then you can make an explicit reference comparison in C# by using Object.ReferenceEquals(this, obj).
In any case, this is why you are seeing true for Equals, since you're passing in a non-null instance of your class.
Incidentally, your comment about NUnit using Equals is true for the same reason; because operators are not polymorphic, there would be no way for a particular class to define custom equality behavior if the Assert function used ==.

a == b checks if they reference the same object.
a.Equals(b) compares the contents.
This is a link to a Jon Skeet article from 2004 that explains it better.

You pretty much answered your question yourself:
I have also over-ridden Equals() in the subclass implementation, which does a very basic check to see whether or not the passed-in object is null and is of the subclass's type. If both those conditions are met, the objects are deemed to be equal.
The == operator hasn't been overloaded - so it's returning false since a and b are different objects. But a.Equals is calling your override, which is presumably returning true because neither a nor b are null, and they're both of the subclass' type.
So your question was "When can a == b be false and a.Equals(b) true?" Your answer in this case is: when you explicitly code it to be so!

In Java a ==b check if the references of the two objects are equals (rougly, if the two objects are the same object "aliased")
a.equals(b) compare the values represented by the two objects.

They both do the same unless they are specifically overloaded within the object to do something else.
A quote from the Jon Skeet Article mentioned elsewhere.
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.
The keyword here is USUALLY. They can be written to do whatever the underlying class wishes and in no way do they have to do the same.

The "==" operate tests absolute equality (unless overloaded); that is, it tests whether two objects are the same object. That's only true if you assigned one to the other, ie.
MyObject a = MyObject.Create();
MyObject b = a;
Just setting all the properties of two objects equal doesn't mean the objects themselves are. Under the hood, what the "==" operator is comparing is the addresses of the objects in memory. A practical effect of this is that if two objects are truly equal, changing a property on one of them will also change it on the other, whereas if they're only similar ("Equals" equal), it won't. This is perfectly consistent once you understand the principle.

I believe that a == b will check if the referenced object is the same.
Usually to see if the value is the same a.Equals(b) is used (this often needs to be overridden in order to work).

Related

Implement Method of Object Class => public virtual bool Equals(obj);

We Have to implement the method of object class => public virtual bool Equals(obj);
without using Equals or Reference Equals Method.
It has to work same as virtual Equals Method.
I can use objA == objB.
I won't give you a code answer, since this is an assignment after all.
Things you want to check:
Null - are both objects null? Is one object null and the other isn't?
object.ReferenceEquals(objA, null) is the old preferable way (since it doesn't potentially use an overriden Equals implementation as == would. With C# 7+, you can also use if (objA is null).
You can now compare if (objA == objB). Note that it's here where objA.Equals(objB) would be used, but since that's not allowed, I guess we can use ==.
There is also objA.GetHashCode() which indicates the potential for equality. I say "potential" because it's possible for two very different objects to have the same hash code. If two objects are equal (and correctly implemented) then they should have the same hash code. In short: you can rely on GetHashCode() to indicate the possibility of equality, but you need to do another check (2) to be sure.
See here for more on the relationship between GetHashCode() and Equals().
And see here for more information about == vs Equals()

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

Explanation:
Equals() compares the values of two objects.
ReferenceEquals() compares their references.
For reference types operator== by default compares references, while for value types it performs (AFAIK) the equivalent of Equals() using reflection.
So. I have a situation where I need to compare two reference types by their values. I can explicitly call Equals() or I can overload operator== to perform the desired comparison.
However, overloading operator== for value comparison kinda-sorta violates the principle of least astonishment. On the other hand explicitly calling two-object Equals looks like overkill.
What is standard practice here?
I know how to override Equals(). The question was whether it is commonly acceptable to override operator== to test for value equality on reference types or whether it is commonly accepted practice to explicitly call Equals/ReferenceEquals to explicitly specify which comparison you want.
What is standard practice?
The "standard practice" is, if you want to check two elements for equality which isn't reference equality, you need to implement IEquatable<T>, which introduces a Equals(T other) method, and override GetHashCode. That way, you control the way these two objects are compared. Usually, this includes overriding the == and != operators as well.
while for value types it performs (AFAIK) equivalent of Equals() using
reflection.
Only if your value type has a member which is a reference type. If it's all value types, it will do a bit comparison of these two objects:
// if there are no GC references in this object we can avoid reflection
// and do a fast memcmp
if (CanCompareBits(this))
return FastEqualsCheck(thisObj, obj);
The question was whether it is commonly acceptable to override
operator== to test for value equality on reference types
It really depends on what you're doing. It is encouraged to override the == operator once you override Equals because you want a consistent behavior value equality semantics. This depends on your definition of equality between two objects.
Although, If an object is mutable, then doing value comparison might result in odd scenarios where two objects are considered equal but later, one is mutated. This should definitely be analyzed on per case basis. Usually, overriding Equals should suffice.
Equals() performs value comparison of two objects.
This is not true. The default behavior of object.Equals on value types is to compare each of the fields using their definition of equality, the default behavior of reference types is to compare their references. It can be overridden to do whatever you want it to do. It is exactly the same as the == operator in this regard.
The only difference between the == operator and Equals is that Equals will perform a virtual dispatch on the first (but not the second) operand, finding the implementation of the method based on the runtime type of that object. The == operator is entirely statically bound; it considers only the compile time type of both operands. Other than this difference in binding both have the same default behaviors, and both can be overridden to provide whatever implementation you want.
The standard practice is to always ensure that the behavior of Equals and operator == is the same for your type. If you override the Equals method to change the equality semantics, then you should also overload the == operator to provide *identical semantics`, and vice versa.
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.
It's a good practice to give a semantic meaning to your code. So, if reference comparison is really something you should care about, use default behaviour for your classes; otherwise your application context dependent logic should be used for comparison. (with consistent behaviour of all the equality members like Equals, GetHashCode and operators)

ReferenceEquals(variable, null) is the same as variable == null?

Basically the title. I see a lot of the former in the code I'm working on and I was wondering why they didn't use the latter. Are there any differences between the two?
Thanks.
Straight from the documentation
Unlike the Equals method and the equality operator, the ReferenceEquals method cannot be overridden. Because of this, if you want to test two object references for equality and are unsure about the implementation of the Equals method, you can call the ReferenceEquals method. However, note that if objA and objB are value types, they are boxed before they are passed to the ReferenceEquals method.
Not really. One can overload operator ==, so you basically can get it return e.g. false always. The recommended usage for this operator is to signify value equality, so (for correcftly implemented operator) basically check against null may return true if the object is semantically null.
See this article for more details and some historical overview.
Another difference is that for value types ReferenceEquals doesn't make much sense: for example, any two "instances" of int 0 have to be considered the same in any sane circumstances. (For purists: I put quotes because, strictly speaking, we cannot talk about instances of a value type.)
The main benefit of ReferenceEquals() is that the intention is much clearer, you are trying to determine if two references are equal, not if the contents of the objects referred to are equal.
It does this by checking for operator == equality between the two references cast to object (since the params are both object), which eliminates any subclass operator == overloads that might confuse the issue (like string's).
So essentially, this:
if (ReferenceEquals(x, y))
Is the same as this:
if (((object)x) == ((object)y))
Though the former is easier to read.
There are definitely times where it comes in handy, especially avoiding infinite recursion when you are overloading operator == yourself:
public class Foo
{
public static bool operator ==(Foo first, Foo second)
{
// can't say if (first == second) here or infinite recursion...
if (ReferenceEquals(first, second))
{
// if same object, obviously same...
return true;
}
// etc.
}
}

Overriding the == operator in non-immutable types

The MSDN Guidelines for Overloading Equals() and Operator == state:
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.
Can anyone explain the reasoning behind the bold?
EDIT - Also, is this guideline relevant to the == operator only, or is it meant for the Equals method as well ?
My educated guess would be to make things operate like the built in types in .NET do, namely that == should work like reference equality where possible, and that Equals should work like value equality where possible. Consider the actual difference between == and Equals:
object myObj = new Integer(4);
object myObj2 = new Integer(4);
//Note that == is only called if the ref'd objects are cast as a type
//overloading it.
myObj == myObj2; //False (???)
myObj.Equals(myObj2); //True (This call is virtual)
//Set the references equal to each other -- note that the operator==
//comparison now works.
myObj2 = myObj;
myObj == myObj2; //True
myObj.Equals(myObj2); //True
This behavior is of course inconsistent and confusing, particularly to new programmers -- but it demonstrates the difference between reference comparisons and value comparisons.
If you follow this MSDN guideline, you are following the guideline taken by important classes such as string. Basically -- if a comparison using == succeeds, the programmer knows that that comparison will always succeed, so long as the references involved don't get assigned to new objects. The programmer need never worry about the contents of the objects being different, because they never will be different:
//Mutable type
var mutable1 = new Mutable(1);
var mutable2 = mutable1;
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //still true, even after modification
//This is consistent with the framework. (Because the references are the same,
//reference and value equality are the same.) Consider if == were overloaded,
//and there was a difference between reference and value equality:
var mutable1 = new Mutable(1);
var mutable2 = new Mutable(1);
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //oops -- not true anymore
//This is inconsistent with, say, "string", because it cannot mutate.
It boils down to that there's no real technical reason for the guideline -- it's just to remain consistent with the rest of the classes in the framework.
Assume you have a mutable type A and you create a set or objects of type A. Adding an object to the set should fail if this object already exists in the set.
Now let's say you add an object to the set, and then you change its properties so that it becomes equal to another object in the set. You've created an illegal state, where there are two objects in the set which are equal.

== or .Equals()

Why use one over the other?
== 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
#John Millikin:
Pointed out below: some value types like 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.
To elaborate:
DateTime is implemented as a struct. All structs are children of System.ValueType.
Since System.ValueType's children live on the stack, there is no reference pointer to the heap, and thus no way to do a reference check, you must compare objects by value only.
System.ValueType overrides .Equals() and == to use a reflection based equality check, it uses reflection to compare each fields value.
Because reflection is somewhat slow, if you implement your own struct, it is important to override .Equals() and add your own value checking code, as this will be much faster. Don't just call base.Equals();
Everyone else pretty much has you covered, but I have one more word of advice. Every now and again, you will get someone who swears on his life (and those of his loved ones) that .Equals is more efficient/better/best-practice or some other dogmatic line. I can't speak to efficiency (well, OK, in certain circumstances I can), but I can speak to a big issue which will crop up: .Equals requires an object to exist. (Sounds stupid, but it throws people off.)
You can't do the following:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
It seems obvious to me, and perhaps most people, that you will get a NullReferenceException. However, proponents of .Equals forget about that little factoid. Some are even "thrown" off (sorry, couldn't resist) when they see the NullRefs start to pop up.
(And years before the DailyWTF posting, I did actually work with someone who mandated that all equality checks be .Equals instead of ==. Even proving his inaccuracy didn't help. We just made damn sure to break all his other rules so that no reference returned from a method nor property was ever null, and it worked out in the end.)
== is generally the "identity" equals meaning "object a is in fact the exact same object in memory as object b".
equals() means that the objects logically equal (say, from a business point of view). So if you are comparing instances of a user-defined class, you would generally need to use and define equals() if you want things like a Hashtable to work properly.
If you had the proverbial Person class with properties "Name" and "Address" and you wanted to use this Person as a key into a Hashtable containing more information about them, you would need to implement equals() (and hash) so that you could create an instance of a Person and use it as a key into the Hashtable to get the information.
Using == alone, your new instance would not be the same.
According to MSDN:
In C#, there are two different kinds of equality: reference equality (also known as identity) and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are two object references and both of them refer to the same object.
...
By default, the operator == tests for reference equality by determining whether two references indicate the same object.
Both Equals and == can be overloaded, so the exact results of calling one or the other will vary. Note that == is determined at compile time, so while the actual implementation could change, which == is used is fixed at compile time, unlike Equals which could use a different implementation based on the run time type of the left side.
For instance string performs an equality test for ==.
Also note that the semantics of both can be complex.
Best practice is to implement equality like this example. Note that you can simplify or exclude all of this depending on how you plan on using you class, and that structs get most of this already.
class ClassName
{
public bool Equals(ClassName other)
{
if (other == null)
{
return false;
}
else
{
//Do your equality test here.
}
}
public override bool Equals(object obj)
{
ClassName other = obj as null; //Null and non-ClassName objects will both become null
if (obj == null)
{
return false;
}
else
{
return Equals(other);
}
}
public bool operator ==(ClassName left, ClassName right)
{
if (left == null)
{
return right == null;
}
else
{
return left.Equals(right);
}
}
public bool operator !=(ClassName left, ClassName right)
{
if (left == null)
{
return right != null;
}
else
{
return !left.Equals(right);
}
}
public override int GetHashCode()
{
//Return something useful here, typically all members shifted or XORed together works
}
}
Another thing to take into consideration: the == operator may not be callable or may have different meaning if you access the object from another language. Usually, it's better to have an alternative that can be called by name.
The example is because the class DateTime implements the IEquatable interface, which implements a "type-specific method for determining equality of instances." according to MSDN.
use equals if you want to express the contents of the objects compared should be equal. use == for primitive values or if you want to check that the objects being compared is one and the same object. For objects == checks whether the address pointer of the objects is the same.
I have seen Object.ReferenceEquals() used in cases where one wants to know if two references refer to the same object
In most cases, they are the same, so you should use == for clarity. According to the Microsoft Framework Design Guidelines:
"DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics."
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators
But sometimes, someone will override Object.Equals without providing equality operators. In that case, you should use Equals to test for value equality, and Object.ReferenceEquals to test for reference equality.
If you do disassemble (by dotPeek for example) of Object, so
public virtual bool Equals(Object obj)
described as:
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
So, is depend on type.
For example:
Object o1 = "vvv";
Object o2 = "vvv";
bool b = o1.Equals(o2);
o1 = 555;
o2 = 555;
b = o1.Equals(o2);
o1 = new List<int> { 1, 2, 3 };
o2 = new List<int> { 1, 2, 3 };
b = o1.Equals(o2);
First time b is true (equal performed on value types), second time b is true (equal performed on value types), third time b is false (equal performed on reference types).

Categories

Resources