Instantiation and Initialization of Value Types vs. Reference Types

int number = new int();

Questions:

  • For reference types, the new operator creates an instance of the type by allocating memory on the heap then initializes it by calling the type's constructor. As seen above, you could do the same for a value type. To me, the line above means that the constructor int() is called to initialize number with a value. I have read that int is a keyword pointing to the struct System.Int32. Therefore, in Visual Studio, I navigate to the struct Int32. Lo and behold, no constructor exists. How exactly is this predefined type initialized to 0 without a constructor?

  • Related to the above, is there a field in the Int32 struct that stores the value?

  • Both for custom structs and classes I can create new instances with the new keyword, without the struct or class actually containing a constructor. In that case, is no initialization done at all of the fields the struct/class contains? Is the only thing that happens that memory is allocated on stack/heap for the value/reference type?

  • Finally, for value types, no new keyword is needed for instantiation and initialization. How exactly does that work on a lower level? Say we do int number = 5;. Is it somehow translated to int a = new int(); a = 5;? If so, how?

  • Thanks a million!


    no constructor [of System.Int32 ] exists.

    All value types have a default constructor:

    Each value type has an implicit default constructor that initializes the default value of that type.

    (end of quote)

    Related to the above, is there a field in the Int32 struct that stores the value?

    Yes, it does:

    [Serializable]
    [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] 
    [System.Runtime.InteropServices.ComVisible(true)]
        public struct Int32 : IComparable, IFormattable, IConvertible
            , IComparable<Int32>, IEquatable<Int32>
            , IArithmetic<Int32> {
            internal int m_value; // <<== Here it is
    
            public const int MaxValue = 0x7fffffff;
            public const int MinValue = unchecked((int)0x80000000);
            ...
    }
    

    Both for custom structs and classes I can create new instances with the new keyword, without the struct or class actually containing a constructor.

    That is not entirely correct: unlike struct s, not all classes have an implicit default constructor; if you define a constructor that takes parameters, the compiler removes the default constructor from your class.

    In that case, is no initialization done at all of the fields the struct/class contains?

    All of the fields that are not initialized explicitly are set to their default values.

    Say we do int number = 5; . Is it somehow translated to int a = new int(); a = 5; int a = new int(); a = 5; ?

    int is a built-in type. The compiler knows how to generate IL for it. The type of int is "baked into" the CIL the compiler generates for the assignment:

    .locals init ([0] int32 a)
    ldc.i4.s   5
    stloc.0
    

    The first line corresponds to the declaration of int a , with or without new . The last two lines do the assignment: load the value of 5 into a register, and store it in the local variable a (at index zero).


  • Even if constructor is not defined, the compiler generates default constructor that initialize the value. Having said that, we should not rely on default constructor to initialize. I think default constructor MyObject() and copy constructor MyObject(MyObject second) are created automatically if it is not explicitly defined.

  • I have not personally looked into Int32 struct but it should have a member that hold the value.

  • As mentioned, when default constructor is not defined, they are automatically created so some initialization is done. Having said that, it is not a good practice to rely on auto created constructor to do the initialization.

  • primitive types do not need and cannot use new keyword (unless when creating an array). When you use new keyword, it seems like int gets "converted" to Int32 which is a class and not a primitive. So, int number = 5 is just that. int a = new int(5) is translated into int a = (int)new Int32(5) This is called boxing. Some operation/collections cannot use primitive types directly, so when primitives are used for such situations, compiler automatically box the primitive types. If it is not needed, no need to box them but use them as primitive ie) don't new them.

  • 链接地址: http://www.djcxy.com/p/85320.html

    上一篇: LINQ,无法创建类型为XXX的常量值。 Only primitive types or enumerati

    下一篇: 值类型与参考类型的实例化和初始化