- Yes, each time you box a value type, a new object is created. More on boxing here.
Equals
check for value equality, not reference equality. Botho
andb
are the same: adouble
with a value of3.0
.3
here is anint
, not adouble
, andEquals
for different types doesn't do any conversion to make them compatible, like the compiler is usually doing.o.Equals(3.0)
will returntrue
.
Repeated boxing makes different references?
-
03-12-2021 - |
Question
I try to understand this code:
double b = 3;
object o = b;
Console.WriteLine(o.Equals(3));//false
Console.WriteLine(o.Equals(b));//true
Console.WriteLine( o == (object)b );//false
- Each new boxing makes different references of object b?
- If 1. is true, why
o.Equals(b)
istrue
? - If
Equals
does not check references, whyo.Equals(3)
isfalse
?
Thanks.
Solution
OTHER TIPS
double b = 3;
creates a new variable in stack with value 3
object o = b;
creates an object in the heap which reference the same place of b
in the stack so you have the same variable with two references this is boxing
o.Equals(3)
is false because it creates a new anonymous variable with value 3 not b
o.Equals(b)
is true because it's the same variable
o == (object)b
is false because ==
is comparing references in memory addresess but Equals
compares the value of the variable itself
See this It explains all about equals behavior.
Every time an effort is made to convert a value type into a reference type, it must be boxed to a new object instance. There is no way the system could do anything else without breaking compatibility. Among other things, while one might expect that boxed value types would be immutable(*), none of them are. Every value type, when boxed, yields a mutable object. While C# and vb.net don't provide any convenient way to mutate such objects, trusted and verifiable code written in C++/CLI can do so easily. Even if the system knew of a heap object that holds an Int32
whose value is presently 23, the statement Object foo = 23;
would have to generate a new Int32
heap object with a value of 23, since the system would have no way of knowing whether something might be planning to change the value of that existing object to 57.
(*)I would argue that they should be; rather than making all boxed objects mutable, it would be much better to provide a means by which struct types like List<T>.Enumerator
could specify customizable boxing behavior. I'm not sure if there's any way to fix that now without totally breaking compatibility with existing code, though.