In Java the following code can return false:
IntegerPlus o1 = new IntegerPlus(1000);
IntegerPlus o2 = o1;
boolean b1 = o1 == o2;
boolean b2 = o1.Equals (o2);
Is this also a problem in C#? Or does C# perform the == in a way where it will always be true even if objects get moved? (I describe the Java issue in greater detail here.)
No.
In C#/.Net hash code is not involved into default implementation of
==
,!=
orEquals
. If object is reference type and it is moved by GC there is nothing outside of this object that will impact default comparisons.Edit: unrelated details about comparison below.
==
andEquals
are not related to each other (except by convention).In C# you have operator == that class/struct can overload. Default behavior is to compare references for reference types, value compare for system value types and for custom 'struct' there is no
==
operator auto-generated. Note that the other comparisonEquals
is not involved into default definition ofoperator ==
.You can also provide your custom
Object.Equals
for class. Good practice for classes the redefine==
orEquals
is to redefine all comparison related methods to work consistently (==
,!=
,Equals(object other)
, andGetHashCode
; possiblyEquals(myType other)
).The only usage of
GetHashCode
in .Net is hash-based collections likeDictionary
,HashSet
. Check GetHashCode Guidelines in C#Obvious sample of custom comparison is
System.String
(string
) - it is reference type but behaves as regular value type in relation to comparison.So back to the original sample:
IntegerPlus
isstruct
without custom "=="/Equals
: there is no==
automatically created (new IntegerPlus(42) == new IntegerPluss(42)
- syntax error). You get value comparison for all fields forEquals
(automatically provided).IntegerPlus
isclass
that does not provide customoperator ==
orEquals
you get reference comparison andnew IntegerPlus(42) != new IntegerPluss(42)
and same forEquals
IntegerPlus
provide only one of==
,!=
,Equals
than behavior will be as defined by custom implementation (likely unexplainable by external observer)IntegerPlus
is either value or reference type and provides consistent set of all 4 comparison related methods you can get value comparison behaviorIn Java, the
==
operator used to be safe with all operand combinations that would compile, and provided neither operand wasfloat
nordouble
, it would implement an equivalence relation. With the advent of autoboxing that is no longer quite true, since the unfortunately-legal comparisons between primitives and their wrapped equivalent is not safe and extends the==
operator in a manner inconsistent with the equivalence relations defined by the types individually.While the equivalence relation which Java would test when both operands were reference types (i.e. reference equivalence) was not always the one programmers were interested in, the behavior of the
==
was consistent with reference types. If variables x, y, and z are any combination of reference types and the expressions x==y, y==z, and x==z all compile, then in every case where two are true, the third will be as well.In C#, the
==
token is used to represent two different operators: the overloadable equality test, and a default reference-equality test. If one of the operands to==
defines an overload which is applicable to the particular combination of operands supplied, the token will be interpreted as an overloadable equality-test operator. Otherwise, if the operands are compatible reference types, it will be interpreted as the default reference-equality test operator. Because the same token is used for both operators and they have different semantics, it cannot in general implement a reliable equivalence relation among reference types unless none of the types in question overload it to represent anything other than reference equality.Given the definitions
String s1=123.ToString(); String s2=123.ToString(); Object o = s1;
, the comparisons1==s2
will return True (using the(string,string)
overload of==
, which sees that they contain the same characters), ando==s1
will return true (using the default reference-equivalence operator to see that they re the same object), buto==s2
will return false (using the default reference-equivalence operator to see that they are distinct objects).If both operands to
==
are of typeObject
, then it will behave as a reference equality test; if they are of other types, though, then the operator may sometimes behave as a reference equality test and sometimes as something else.