c# - When is Double's == operator invoked? -
it started trick question posed me.. (it's mentioned in book - c# in nutshell) here's gist of it.
double = double.nan; console.writeline(a == a); // => false console.writeline(a.equals(a)); // => true
the above doesn't seem right. should == (reference equality) & both should consistent.
seems double overloads == operator. confirmed reflector follows:
[__dynamicallyinvokable] public static bool operator ==(double left, double right) { homecoming (left == right); }
strange looks recursive , no mention of nan specific behavior. why homecoming false?
so add together more code distinguish
var x = "abc"; var y = "xyz"; console.writeline(x == y); // => false
now see
l_0001: ldc.r8 nan l_000a: stloc.0 l_000b: ldloc.0 l_000c: ldloc.0 l_000d: ceq l_000f: phone call void [mscorlib]system.console::writeline(bool) l_0014: nop l_0015: ldloca.s l_0017: ldloc.0 l_0018: phone call instance bool [mscorlib]system.double::equals(float64) l_001d: phone call void [mscorlib]system.console::writeline(bool) l_0022: nop l_0023: ldstr "abc" l_0028: stloc.1 l_0029: ldstr "xyz" l_002e: stloc.2 l_002f: ldloc.1 l_0030: ldloc.2 l_0031: phone call bool [mscorlib]system.string::op_equality(string, string) l_0036: phone call void [mscorlib]system.console::writeline(bool)
for doubles, == operator phone call translates ceq
il opcode where strings, translates system.string::op_equality(string, string). sure plenty documentation ceq
specifies special-cased floating point numbers , nan. explains observations.
questions:
why op_equality defined on double ? (and implementation not factor in nan specific behavior) when invoked ?reflector's erroneous interpretation
the decompilation seeing reflector bug in reflector. reflector needs able decompile function 2 doubles beingness compared; in functions, find ceq
emitted right code. result, reflector interprets ceq
instruction == between 2 doubles help decompile function 2 doubles beingness compared.
by default, value types don't come == implementation. (don't user-defined structs inherit overloaded == operator?) however, of built-in scalar types have explicitly overloaded operator compiler translates appropriate cil. overload contains simple ceq
based comparison, dynamic/late-bound/reflection-based invokes of == operator overload won't fail.
for predefined value types, equality operator (==) returns true if values of operands equal, false otherwise. reference types other string, == returns true if 2 operands refer same object. string type, == compares values of strings.
-- http://msdn.microsoft.com/en-us/library/53k8ybth.aspx
what said implies == uses reference type semantics comparing of double
. however, since double
value type, uses value semantics. why 3 == 3
true, though they're different stack objects.
you can think of compiler translation how linq's queryable object contains extension methods with code in them, compiler translates these calls look trees passed linq provider instead. in both cases, underlying function never gets called.
double's comparing semanticsthe documentation double allude how ceq
cil instruction works:
if 2 double.nan values tested equality calling equals method, method returns true. however, if 2 nan values tested equality using equality operator, operator returns false. when want determine whether value of double not number (nan), alternative phone call isnan method.
-- http://msdn.microsoft.com/en-us/library/ya2zha7s.aspx
raw compiler sourceif in decompiled c# compiler source, you'll find next code handle direct translation of double comparisons ceq
:
private void emitbinarycondoperator(boundbinaryoperator binop, bool sense) { int num; constantvalue constantvalue; bool flag = sense; binaryoperatorkind kind = binop.operatorkind.operatorwithlogical(); if (kind <= binaryoperatorkind.greaterthanorequal) { switch (kind) { ... case binaryoperatorkind.equal: goto label_0127; ... } } ... label_0127: constantvalue = binop.left.constantvalue; if (((constantvalue != null) && constantvalue.isprimitivezeroornull) && !constantvalue.isfloating) { ... return; } constantvalue = binop.right.constantvalue; if (((constantvalue != null) && constantvalue.isprimitivezeroornull) && !constantvalue.isfloating) { ... return; } this.emitbinarycondoperatorhelper(ilopcode.ceq, binop.left, binop.right, sense); return; }
the above code roslyn.compilers.csharp.codegen.codegenerator.emitbinarycondoperator(...)
, , added "..."'s in order create code more readable purpose.
c# .net
No comments:
Post a Comment