Posted By: Red5 | Jun 27th, 2008 @ 11:04 AM
page 2 of 2
Comments: 32 | Views: 1958
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
Much as I love your ad-hom attacks and referring to my good-intentioned posts as something that people either learn in .NET day 1 or referring to it as a twitch, it would help if you checked you were right before attacking my posts.

You arn't:

        class ComplexNumber
        {
            public int RealPart {get; set;}
            public int ImaginaryPart {get; set;}

            public static bool operator ==(ComplexNumber a, ComplexNumber b)
            {
                Console.WriteLine("A method call happened. Note that this takes much longer than a reference check");

                return (a.RealPart == b.RealPart) && (a.ImaginaryPart == b.ImaginaryPart);
            }
            public static bool operator !=(ComplexNumber a, ComplexNumber b)
            {
                return !(a == b);
            }
        }

        static void Main(string[] args)
        {
            ComplexNumber cmplx = null;

            Console.WriteLine("Let's check shall we?");
            try
            {
                Console.WriteLine("Console.WriteLine( cmplx == null ) yields ...");
                Console.WriteLine(cmplx == null);
            }catch(Exception e){
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Threw exception: " + e);
                Console.ForegroundColor = ConsoleColor.Gray;
            }

            Console.WriteLine();
            try
            {
                Console.WriteLine("Console.WriteLine( (object)cmplx == null ) yields ...");
                Console.WriteLine((object)cmplx == null);
            }
            catch (Exception e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Threw exception: " + e);
                Console.ForegroundColor = ConsoleColor.Gray;
            }

            Console.WriteLine("Press [ENTER] to exit");
            Console.ReadLine();

        }


Prints:

Let's check shall we?
Console.WriteLine( cmplx == null ) yields ...
A method call just happened. Note that this takes much longer than a reference check
Threw exception: System.NullReferenceException: Object reference not set to an instance of an object.

Console.WriteLine( (object)cmplx == null ) yields ...
True
Press [ENTER] to exit



That's the whole point of my past post is that Microsoft do cast to object before the == in order to produce il of the form:

ldarg.0
brfalse (dst)

rather than

ldarg.0
call System.String.op_eq
brfalse (dst)



I'd prefer it if you made constructive critisism in future rather than attacking my style or motives. Thanks.
stevo_
stevo_
Human after all
I'd prefer it if you stopped talking out of your ass.. I told you I've checked the IL.. you are just popping IL out of your mind.. and I'd prefer it if you stopped making posts where you feel you have to divert the topic in favour of you doing the meta-equiv of a "muscle flex".. in terms of geeky muscle flex.. you are neither the best or worst here.. but certainly no one here gives a crap about it..

Edit:

Oh haha, wait I've actually read your sample now.. you are posting an example by where you purposely overload the operators on a custom type in order to prove that when you orderload an operator.. your replacement method gets called instead of the default memory reference check..

Thats cute, and sure- your right.. but thats not what string equality compiles to..

I'm waiting on you to try and twist this again..
A follow up question if I may. It's just something that popped into my mind while reading you're example code (and I can't check right now).

Does one not have to always cast to an object to do null checking when overloading the == operator (and similarly .Equals())? If you think about it, if you don't then you'll either get an exception as evildictaitor showed, or you'll end up in an infinite recursive loop.

This will throw stackoverflow exception, no?
public static bool operator ==(ComplexNumber a, ComplexNumber b)
{
    if((a == null && b!= null) || (a != null && b==null)) return false;
    if(a == null && b == null) return true;
    return (a.RealPart == b.RealPart) && (a.ImaginaryPart ==     b.ImaginaryPart);
}

Correct would be:
public static bool operator ==(ComplexNumber a, ComplexNumber b)
{
    object oa = (object)a;
    object ob = (object)b;
    if((oa == null && ob!= null) || (oa != null && ob==null)) return false;
    if(oa == null && ob == null) return true;
    return (a.RealPart == b.RealPart) && (a.ImaginaryPart ==     b.ImaginaryPart);
}

Right?
stevo_
stevo_
Human after all
Yes you probably would get a stack overflow if you didn't cast to object, as you say- you are recursively calling your own overload.
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
You are no doubt aware that strings overload == operator themselves, and thus my argument is not arbitrary as you suppose ....
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
You code can be simplied slightly to

public static bool operator ==(ComplexNumber a, ComplexNumber b)
{
  if( (object) a == null)
    // then they are equivilent only if both are null
    return (object) b == null;
  if( (object)b == null)
    // then since a is non-null, they are different
    return false;

    return (a.RealPart == b.RealPart) && (a.ImaginaryPart ==     b.ImaginaryPart);
}

And dropping the (object) downcasts as you mention causes a stack-overflow. Thanks for helping me clarify my point.

As a side-point (which is where this all started) if a class overloads the == operator, such as the System.String class, then == null diverts through that method, thus causing a method call. If you cast-down to an object the compiler just checks that the object reference isn't null in place, which speeds things up a bit.
stevo_
stevo_
Human after all
String does overload the equality operators but that doesn't change the fact the IL doesn't call them (at least when checking against null)..

Theres no speed up to casting to an object because theres no difference.. I tested 20 billion iterations of null checking either way for a string.. and both take around 1 minute and 31 seconds to complete.. the fractions of a second are so small - interestingly however.. the casting to object was always the slower.. no matter if it was tested first or last.. but I'll put that down to complete chance..
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
That's interesting, and I concede that for string the Microsoft C# compiler appears to optimise away the superfluous call to the string equality, which is pretty clever.

That said, selecting pretty much any other class that overloads operator ==, my original contention holds

for example:

    class Program
    {
        static Version foo;

        static void Main(string[] args)
        {
            Console.WriteLine((object)foo == null);
        }
    }

compiles to

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldsfld     class [mscorlib]System.Version ConsoleApplication1.Program::foo
  IL_0006:  ldnull
  IL_0007:  ceq
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_000e:  nop
  IL_000f:  ret
} // end of method Program::Main

whereas

    class Program
    {
        static Version foo;

        static void Main(string[] args)
        {
            Console.WriteLine(foo == null);
        }
    }

compiles to

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       19 (0x13)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldsfld     class [mscorlib]System.Version ConsoleApplication1.Program::foo
  IL_0006:  ldnull
  IL_0007:  call       bool [mscorlib]System.Version::op_Equality(class [mscorlib]System.Version,
                                                                  class [mscorlib]System.Version)
  IL_000c:  call       void [mscorlib]System.Console::WriteLine(bool)
  IL_0011:  nop
  IL_0012:  ret
} // end of method Program::Main



But with strings, comparison to null does not require down-casting to object to get any speedup., so yes, you're right in this instance.
page 2 of 2
Comments: 32 | Views: 1958
Microsoft Communities