dotNET Rant [modified]
-
A subtlety of implicit boxing. What you did was create 2 new objects on the heap, each one pointing to an integer, 0. Then, you compared equality on the objects, not on the integers. You expected them to be equal because they're pointing to integers that happen to be equal, but you were comparing the objects, not the integers. To compare equality on the integers,
bool same = (int)one == (int)two;
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah HimangoJudah Himango wrote:
What you did was create 2 new objects on the heap, each one pointing to an integer, 0.
… and did a reference comparison.
-
ok, this is not a programming question. It's a rant! given,
object one = 0;
object two = 0;
bool same = one == two;what would you expect the value of
same
to be? WRONG! it's false! Whoever thought that was a valid result, is cracked!:mad::mad::mad::mad::mad: [edit] so, after going home and resting my brain a bit. it seems as though i'm the one that was cracked. thanks for the refresher course everyone. it is of course doing a reference comparison. which is correct. you all know how it is when you struggle with something and get too close to the trees to see the forest. anyway thanks to everyone for being your normally brutally honest selves. cheers. :-D [/edit]Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/modified on Friday, May 7, 2010 1:08 AM
.NET is irrelevant here, we all know one and two are not the same. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
Prolific encyclopedia fixture proof-reader browser patron addict?
We all depend on the beast below.
-
ahmed zahmed wrote:
what would you expect the value of same to be?
It has to be false. What else can it be? I am pretty sure lot of other programmers here would have answered false too. :confused:
Rama Krishna Vavilala wrote:
It has to be false. What else can it be?
Why? One would expect that the comparators of the boxed values would be used. so, the result would be true, as I initially expected. I understand what's happening, but I don't understand why the dotNETtors decided this was correct.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
A subtlety of implicit boxing. What you did was create 2 new objects on the heap, each one pointing to an integer, 0. Then, you compared equality on the objects, not on the integers. You expected them to be equal because they're pointing to integers that happen to be equal, but you were comparing the objects, not the integers. To compare equality on the integers,
bool same = (int)one == (int)two;
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himangobut in code that is comparing boxed values, you don't know what the boxed types are so it's not as simple as casting to a known type.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
.NET is irrelevant here, we all know one and two are not the same. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
Prolific encyclopedia fixture proof-reader browser patron addict?
We all depend on the beast below.
:laugh: :laugh: :laugh: ;P ;P :((
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
Rama Krishna Vavilala wrote:
It has to be false. What else can it be?
Why? One would expect that the comparators of the boxed values would be used. so, the result would be true, as I initially expected. I understand what's happening, but I don't understand why the dotNETtors decided this was correct.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/== is ref comparison so I would not expect the references to be equal. The right comparison would have been to use Equals.
-
== is ref comparison so I would not expect the references to be equal. The right comparison would have been to use Equals.
== calls Equals. Use Reflector.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
but in code that is comparing boxed values, you don't know what the boxed types are so it's not as simple as casting to a known type.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/Code that compares boxed value types has to know about the value it's trying to compare, otherwise it isn't a very smart boxed value type comparer. Generics and EqualityComparer might help you here.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango -
Code that compares boxed value types has to know about the value it's trying to compare, otherwise it isn't a very smart boxed value type comparer. Generics and EqualityComparer might help you here.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah HimangoThe context is comparing DbParameter's (parameters to a PreparedCommand) to know whether the result is cached or not. So it's not as simple as it may seem. In any case, seems to me that since only primitives get boxed, then that condition should be checked in the object.Equals code. Thanks for the suggestion.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
== calls Equals. Use Reflector.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/Let's try
object x = 0;
object y = 0;
Console.WriteLine(x == y);Result:
.locals init ( \[0\] object x, \[1\] object y) L\_0000: nop L\_0001: ldc.i4.0 L\_0002: box int32 L\_0007: stloc.0 // x is boxed int L\_0008: ldc.i4.0 L\_0009: box int32 L\_000e: stloc.1 // y is boxed int L\_000f: ldloc.0 L\_0010: ldloc.1 L\_0011: ceq // comparison does NOT call Equals L\_0013: call void \[mscorlib\]System.Console::WriteLine(bool) L\_0018: nop L\_0019: br.s L\_001b L\_001b: ret
-
Let's try
object x = 0;
object y = 0;
Console.WriteLine(x == y);Result:
.locals init ( \[0\] object x, \[1\] object y) L\_0000: nop L\_0001: ldc.i4.0 L\_0002: box int32 L\_0007: stloc.0 // x is boxed int L\_0008: ldc.i4.0 L\_0009: box int32 L\_000e: stloc.1 // y is boxed int L\_000f: ldloc.0 L\_0010: ldloc.1 L\_0011: ceq // comparison does NOT call Equals L\_0013: call void \[mscorlib\]System.Console::WriteLine(bool) L\_0018: nop L\_0019: br.s L\_001b L\_001b: ret
ok, an MSIL lawyer! perhaps, it got optimized away. In any case, the result is false.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
== calls Equals. Use Reflector.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ahmed zahmed wrote:
== calls Equals
No. It calls Equals only when some class has overloaded the == operator (aka string). For objects == always means reference comparison. Also if it called Equals, you would not have had the problem in the first place. Because, one.Equals(two) will return true in your application. [Edit] Thanks for the one vote [/Edit]
-
ok, this is not a programming question. It's a rant! given,
object one = 0;
object two = 0;
bool same = one == two;what would you expect the value of
same
to be? WRONG! it's false! Whoever thought that was a valid result, is cracked!:mad::mad::mad::mad::mad: [edit] so, after going home and resting my brain a bit. it seems as though i'm the one that was cracked. thanks for the refresher course everyone. it is of course doing a reference comparison. which is correct. you all know how it is when you struggle with something and get too close to the trees to see the forest. anyway thanks to everyone for being your normally brutally honest selves. cheers. :-D [/edit]Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/modified on Friday, May 7, 2010 1:08 AM
Nooo... that's correct. Otherwise, what would you do with this:
int one = 0 ;
int two = 0 ;bool same = (object) one == (object) two ;
Shouldn't this perform the same reference comparison of your code? (Man, you miss one closing quote... :-O )
modified on Thursday, May 6, 2010 7:38 PM
-
Nooo... that's correct. Otherwise, what would you do with this:
int one = 0 ;
int two = 0 ;bool same = (object) one == (object) two ;
Shouldn't this perform the same reference comparison of your code? (Man, you miss one closing quote... :-O )
modified on Thursday, May 6, 2010 7:38 PM
eh? why are you showing me javascript?
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
ok, an MSIL lawyer! perhaps, it got optimized away. In any case, the result is false.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ahmed zahmed wrote:
perhaps, it got optimized away.
I very much doubt it. The C# compiler only seems to do trivial constant folding (without using commutativity etc) and some limited dead code elimination (after an unconditional return etc) The JIT compiler does the rest (which is not a lot, either) If it changes the result it is not an "optimization" but a bug. And, this was a Debug build, as can easily be seen. Here is the same code compiled in Release mode.
.locals init ( \[0\] object x, \[1\] object y) L\_0000: ldc.i4.0 L\_0001: box int32 L\_0006: stloc.0 L\_0007: ldc.i4.0 L\_0008: box int32 L\_000d: stloc.1 L\_000e: ldloc.0 L\_000f: ldloc.1 L\_0010: ceq L\_0012: call void \[mscorlib\]System.Console::WriteLine(bool) L\_0017: ret
-
ahmed zahmed wrote:
perhaps, it got optimized away.
I very much doubt it. The C# compiler only seems to do trivial constant folding (without using commutativity etc) and some limited dead code elimination (after an unconditional return etc) The JIT compiler does the rest (which is not a lot, either) If it changes the result it is not an "optimization" but a bug. And, this was a Debug build, as can easily be seen. Here is the same code compiled in Release mode.
.locals init ( \[0\] object x, \[1\] object y) L\_0000: ldc.i4.0 L\_0001: box int32 L\_0006: stloc.0 L\_0007: ldc.i4.0 L\_0008: box int32 L\_000d: stloc.1 L\_000e: ldloc.0 L\_000f: ldloc.1 L\_0010: ceq L\_0012: call void \[mscorlib\]System.Console::WriteLine(bool) L\_0017: ret
Whatever, the point is, it didn't do as, at least, *I* expected. Perhaps its a compiler optimization that it's able to do from context. Try this:
bool compare(object a, object b)
{
return a == b;
}bool result = compare(0, 0);
I'm not sure if the actual result or my expectation is correct. In any case, I wasted a lot of time on this because staring at the code it sure looked like it should "work."
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
Nooo... that's correct. Otherwise, what would you do with this:
int one = 0 ;
int two = 0 ;bool same = (object) one == (object) two ;
Shouldn't this perform the same reference comparison of your code? (Man, you miss one closing quote... :-O )
modified on Thursday, May 6, 2010 7:38 PM
-
ahmed zahmed wrote:
== calls Equals
No. It calls Equals only when some class has overloaded the == operator (aka string). For objects == always means reference comparison. Also if it called Equals, you would not have had the problem in the first place. Because, one.Equals(two) will return true in your application. [Edit] Thanks for the one vote [/Edit]
The one vote wasn't me. Look, whether I use == or .Equals should be semantically the same. so, leaving null values out of the picture, the result of a == b should be the same as calling a.Equals(b). if not, then something or other is fracked.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ -
Whatever, the point is, it didn't do as, at least, *I* expected. Perhaps its a compiler optimization that it's able to do from context. Try this:
bool compare(object a, object b)
{
return a == b;
}bool result = compare(0, 0);
I'm not sure if the actual result or my expectation is correct. In any case, I wasted a lot of time on this because staring at the code it sure looked like it should "work."
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/This in Main:
L\_0000: ldc.i4.0 L\_0001: box int32 L\_0006: ldc.i4.0 L\_0007: box int32 L\_000c: call bool Test.Program::compare(object, object) L\_0011: pop L\_0012: ret
This in compare:
L\_0000: ldarg.0 L\_0001: ldarg.1 L\_0002: ceq // still a reference comparison.. L\_0004: ret
More importantly, I would like to point you to page 41 of 553 in ECMA-364 2nd edition where it says "Two expressions of type object are considered equal if both refer to the same object, or if both are null." The spec is usually right..
-
The one vote wasn't me. Look, whether I use == or .Equals should be semantically the same. so, leaving null values out of the picture, the result of a == b should be the same as calling a.Equals(b). if not, then something or other is fracked.
Fight Big Government:
http://obamacareclassaction.com/
http://obamacaretruth.org/ahmed zahmed wrote:
whether I use == or .Equals should be semantically the same.
But it is not. Consider this:
string s = "ahmed";
string s1 = "zahmed";Console.WriteLine(s.Equals(s1.Substring(1)));
Console.WriteLine(s == (s1.Substring(1)));Console.WriteLine((object)s == (s1.Substring(1)));
What do you think the output will be? It has to be: 1. true 2. true (the operator == in string is overloaded) 3. false (reference comparison)