值类型与参考类型的实例化和初始化

时间:2014-08-22 14:33:41

标签: c# types instantiation value-type reference-type

  

int number = new int();

问题:

  1. 对于引用类型, new 运算符通过在堆上分配内存然后通过调用类型的构造函数来初始化它来创建该类型的实例。如上所示,您可以对值类型执行相同操作。对我来说,上面的行意味着调用构造函数int()以使用值初始化 number 。我已经读过int是一个指向struct System.Int32 的关键字。因此,在Visual Studio中,我导航到结构Int32。瞧,没有构造函数存在。如果没有构造函数,这个预定义类型究竟是如何初始化为0的?

  2. 与上述内容相关,Int32结构中是否存在存储值的字段?

  3. 对于自定义结构和类,我都可以使用 new 关键字创建新实例,而实际上不包含构造函数的结构或类。在这种情况下,是否在struct / class包含的所有字段中都没有进行初始化?是否唯一发生的事情就是在堆栈/堆上为值/引用类型分配内存?

  4. 最后,对于值类型,实例化和初始化不需要 new 关键字。这究竟是如何在较低级别上工作的?假设我们 int number = 5; 。它以某种方式转换为 int a = new int(); a = 5; ?如果是这样,怎么样?

  5. 万分感谢!

2 个答案:

答案 0 :(得分:2)

  

没有[System.Int32]的构造函数。

所有value types have a default constructor

  

每个值类型都有一个隐式默认构造函数,用于初始化该类型的默认值。

(引用结束)

  

与上述相关,Int32 struct中是否存在存储值的字段?

是的,确实如此:

[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);
        ...
}
  

对于自定义结构和类,我可以使用new关键字创建新实例,而实际上不包含构造函数的结构或类。

这不完全正确:与struct不同,并非所有类都有隐式默认构造函数;如果定义一个带参数的构造函数,编译器将从类中删除默认构造函数。

  

在这种情况下,是否在struct / class包含的所有字段中都没有进行初始化?

未明确初始化的所有字段都设置为默认值。

  

说我们做int number = 5;。它以某种方式翻译为int a = new int(); a = 5;

int是内置类型。编译器知道如何为它生成IL。 int的类型是&#34;烘焙到&#34;编译器为赋值生成的CIL:

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

第一行对应int a的声明,有或没有new。最后两行执行赋值:将5的值加载到寄存器中,并将其存储在局部变量a中(索引为零)。

答案 1 :(得分:-3)

  1. 即使没有定义构造函数,编译器也会生成初始化值的默认构造函数。话虽如此,我们不应该依赖默认构造函数来初始化。我认为如果未明确定义默认构造函数MyObject()和复制构造函数MyObject(MyObject second),则会自动创建。

  2. 我没有亲自查看Int32结构,但它应该有一个保存该值的成员。

  3. 如上所述,当未定义默认构造函数时,会自动创建它们,以便完成一些初始化。话虽如此,依靠自动创建的构造函数进行初始化并不是一个好习惯。

  4. 原始类型不需要也不能使用new关键字(除非在创建数组时)。当你使用new关键字时,似乎int被“转换”为Int32,这是一个类,而不是一个原始的。所以,int number = 5就是这样。 int a = new int(5)被翻译成int a =(int)new Int32(5)这称为拳击。某些操作/集合不能直接使用基本类型,因此当基元用于此类情况时,编译器会自动封装基元类型。如果不需要,则不需要将它们装箱但是将它们用作原始的,即不要新建它们。