Tech Off Thread

13 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

null + null = ?

Back to Forum: Tech Off
  • User profile image
    Londoner

    What would you expect the result of the following code to be?

    [STAThread]

    static void Main( string[] args )

    {

          Console.WriteLine( ( null + null ).GetType() );

          Console.ReadLine();

    }



    Now compile it and see for yourself. Magic...

  • User profile image
    Londoner

    Here is another one for you:

    class Class1
    {
          public int c = true;  // <---- It compiles!!
           
          public Class1(): this(0) {}
          public Class1(int i): this() {} 
          [STAThread]
          static void Main(string[] args)
          {
                 
          }
    }

  • User profile image
    Manip

    You are aware that both true, false and null have a value. Null is ascii 0, so it is a correct string. 

    true = 1, the value. And false = 0, the value. 

    Try this:

    int bluh;
    bluh = Convert.ToInt32 (false);
    Console.WriteLine( bluh );
    bluh = Convert.ToInt32 (true);
    Console.WriteLine( bluh );
    Console.ReadLine();

  • User profile image
    Londoner

    That doesnt however explain  to me why (null + null) will result in string.Empty (see IL below)

      IL_0000:  ldstr      ""
      IL_0005:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
      IL_000a:  call       void [mscorlib]System.Console::WriteLine(object)
      IL_000f:  call       string [mscorlib]System.Console::ReadLine()

    I understand that overloaded string + operator is being called and nulls converted to "". But why string is chosen in the first place? IMO it should not be possible to compile this code at all...

    Regarding my seconds example, C# compiler is being confused by the use of constructors and does no type checking, so that the following would still compile :

    public string h = 56;
    public DateTime k = 0;
    public int i = "dfsf";
    public Class1() : this(0)
    {}

    public Class1(int i) : this()
    {}









  • User profile image
    Shining Arcanine

    Londoner wrote:
    That doesnt however explain  to me why (null + null) will result in string.Empty (see IL below)


    Maybe it nulifies itself sort of like when you mutiple a negitive times a negitive...

  • User profile image
    jj5

    The reason for null + null == String.Empty will be because the + operator is defined on string and takes two string references. It would seem that concatenation of two null strings has been defined as an empty string.

    It's an interesting observation. I guess somewhere it's probably defined that the string operators will always be called in this case. I tried to create a class that also defined a + overload but the string overload was always called..

    There're tonnes of little things like this in framework. Try casting null to a SqlBinary for example, then try casting null to SqlBoolean.. they're both nullable types.. Wink

    Did you know that true is an operator..?

    John.

  • User profile image
    jj5

    I think I jumped the gun a little too quick on this one. I didn't look at the IL. Obviously what happened here is that C# compiler decided that null + null was a constant expression and substitued it with an empty string.

    So it was the C# compiler that decided that the type of the null references concatenation was 'string'. I'm not sure where this behavior would be documented, but I'm sure it would be..

    You can't compile something like this:

          object a = null;
          object b = null;
          Console.WriteLine((a + b).GetType());

    Nor can you compile something like this:

      public class MyType {
        public static MyType operator + (object a, object b) {
          // ..
        }
      }

    I can't imagine any other 'null + null' case that the CLR might actually see at runtime (i.e. where the type information was missing). With the type information present there are rules for determining which operator overload will get called..

    So, this is a C# language feature it would seem. I wonder what happens in other .NET languages..

    John.

  • User profile image
    Martin

    Londoner wrote:
    Here is another one for you:

    class Class1
    {
          public int c = true;  // <---- It compiles!!
           
          public Class1(): this(0) {}
          public Class1(int i): this() {} 
          [STAThread]
          static void Main(string[] args)
          {
                 
          }
    }



    It compiles because there is no syntax error, and the compiler can make code for it, just as it does for this:

    public void First()
    {
      this.Second();
    }

    public void Second()
    {
      this.First();
    }

    It's no different. The compiler isn't fooled, it is doing exactly what you told it to do.

  • User profile image
    spod

    Londoner wrote:
    What would you expect the result of the following code to be?

    [STAThread]

    static void Main( string[] args )

    {

          Console.WriteLine( ( null + null ).GetType() );

          Console.ReadLine();

    }



    Now compile it and see for yourself. Magic...


    hey londoner - sorry for the very late reply Smiley...i got an answer from one of the c# compiler guys on this:

    The compiler is applying "overload resolution" on the + operator to pick the best +. The only predefined + operator for which null can be used as an argument is the string concatenation operator.
     
    Note that this will change in Whidbey. With support for nullable types, there are now other predefined + operators that work, like +(int?, int?). This code will then generate an ambiguity error.

  • User profile image
    Kenneth.L

    Londoner wrote:
    Here is another one for you:

    class Class1
    {
          public int c = true;  // <---- It compiles!!
           
          public Class1(): this(0) {}
          public Class1(int i): this() {} 
          [STAThread]
          static void Main(string[] args)
          {
                 
          }
    }


    The first, the "public int c = true; " is front of the constructor, so that it will be initialized before them.

    The second, true equals 0 and false equals 1 in some way like bit of SqlDbType.

  • User profile image
    footballism

    Londoner wrote:
    Here is another one for you:

    class Class1
    {
          public int c = true;  // <---- It compiles!!
           
          public Class1(): this(0) {}
          public Class1(int i): this() {} 
          [STAThread]
          static void Main(string[] args)
          {
                 
          }
    }

    yes,this class(Class1) can be compiled,but why the following cannot be compiled.

    class Class1
    {
          public int c = true;  // <---- It compiles!!
           
          public Class1(int i){} 
          [STAThread]
          static void Main(string[] args)
          {      
          }
    }


    I am pretty confused when the C# compiler issues a compile-time error
    saying that there is no explicit conversion from boolean type to int32 type.
    I just wanna simply ask why?

  • User profile image
    spod

    I think this is a ( minor )compiler bug. The self referencing constructors seem to have it pretty confused - it should probably throw a diagnostic here.

    It's somewhat of an edge case( you could never construct a class1 without a stack overflow ).

    What's happening is that the compiler is seeing that it can never construct one of these things so isn't rewriting the class to add the initializers to the constructor. So it sees

    public int c; // ( no = true )


    This doesn't just work for bools of course - this class gives the appearance of being a general "reinterpret_cast<> class Smiley" able to convert any type to any type...so the following compiles fine also...

    class Class1
    {
    public int c = true; // <---- It compiles!!
    public DateTime d = 10.243;
    public float f = "Rabbit";
    public Guid g = new DateTime( "10/10/2002 10:53Z" );
    public Class1(): this(0) {}
    public Class1(int i) : this() {}
    }

     

  • User profile image
    footballism

    so, the recursion invocation of constructors fool the C# compiler into believing the field 'c' isn't initialized.so you can assign any type of values to it,yes,it's really a minor bug. 

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.