C# 什么';这两种实例化类属性的方法有什么区别?
这里是基本的C#问题 在声明类属性/字段时或在相关对象的构造函数中创建该类属性/字段的实例之间有什么区别。例如:C# 什么';这两种实例化类属性的方法有什么区别?,c#,C#,这里是基本的C#问题 在声明类属性/字段时或在相关对象的构造函数中创建该类属性/字段的实例之间有什么区别。例如: public class MyClass { public MyObject = new MyObject(); } vs 带有初始值设定项的字段在调用基构造函数之前初始化,而如果初始值设定项在主体中,则只有在调用基构造函数之后才会执行 如果基构造函数调用虚拟方法,这可能是相关的,但就我个人而言,我会尽量避免这种情况 示例代码: public class Base {
public class MyClass
{
public MyObject = new MyObject();
}
vs
带有初始值设定项的字段在调用基构造函数之前初始化,而如果初始值设定项在主体中,则只有在调用基构造函数之后才会执行 如果基构造函数调用虚拟方法,这可能是相关的,但就我个人而言,我会尽量避免这种情况 示例代码:
public class Base
{
public Base()
{
Dump();
}
public virtual void Dump() {}
}
public class Child : Base
{
private string x = "Initialized at declaration";
private string y;
public Child()
{
y = "Initialized in constructor";
}
public override void Dump()
{
Console.WriteLine(x); // Prints "Initialized at declaration"
Console.WriteLine(y); // Prints "" as y is still null
}
}
需要注意的是,(在C#)对字段的初始值设定项赋值将在调用任何基类构造函数之前发生(关于VB是否可以被迫做同样的事情的说明就是明证) 这意味着您不能使用初始值设定项语法引用基类的字段(即,您不能直接将此VB转换为C#):
您还可以使用静态构造函数,该构造函数在可以初始化静态变量的任何其他构造函数之前被调用
public class Bus
{
private static object m_object= null;
// Static constructor:
static Bus()
{
m_object = new object();
System.Console.WriteLine("The static constructor invoked.");
}
public static void Drive()
{
System.Console.WriteLine("The Drive method invoked.");
}
}
class TestBus
{
static void Main()
{
Bus.Drive();
}
}
我编译这些C代码:
我得到了IL汇编:
MyClass1:
.class public auto ansi beforefieldinit test.MyClass1
extends [mscorlib]System.Object
{
.field public class test.MyObject MyObject
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// code size: 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void test.MyObject::.ctor()
IL_0006: stfld class test.MyObject test.MyClass1::MyObject
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: nop
IL_0012: ret
} // end of method MyClass1::.ctor
} // end of class test.MyClass1
MyClass2:
.class public auto ansi beforefieldinit test.MyClass2
extends [mscorlib]System.Object
{
.field public class test.MyObject MyObject
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// code size: 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: newobj instance void test.MyObject::.ctor()
IL_000e: stfld class test.MyObject test.MyClass2::MyObject
IL_0013: nop
IL_0014: ret
} // end of method MyClass2::.ctor
} // end of class test.MyClass2
很明显,区别仅在于对基类构造函数(System.Object::.ctor())、MyObject初始值设定项(test.MyObject::.ctor())和类初始值设定项(stfld class test.MyObject test.MyClass2::MyObject)的调用顺序
在第一种情况下,MyClass1初始化如下:
- MyObject初始值设定项
- 类初始值设定项(构造函数分配)
- 基类初始值设定项(基类构造函数)
- 基类初始值设定项(基类构造函数)
- MyObject初始值设定项
- 类初始值设定项(构造函数分配)
MyObject=new MyObject()
不是初始值设定项,它只是一个赋值语句。初始值设定项在C#@Cody Gray中有一个特定的含义:“…在C#中,对字段的初始值设定项赋值将在调用任何基类构造函数之前发生”-这是一个LIE@Damien_The_Unbeliever在MyClass2中,在基类构造函数调用+1之后也会调用该字段的初始值设定项assignment,我的理解是,在声明处初始化字段允许编译器/JITer进行一些优化,否则它不会在构造函数中进行初始化。我相信我在“.NET Framework设计指南”中读到了这一点,作为他们将字段初始化作为“最佳实践”的理由,但我不再确定了。@Cody:说实话,我不确定。我个人在编写代码时不会考虑这一点——我只会坚持用最清晰的方式表达意图。@Jon Skeet错误:子类没有继承到基中code@JonSkeet,关于问题,编译器将示例2(有问题)转换为示例1,如果它是在Reflector@Adeel:依我看,这基本上是Reflector中的一个bug。看看IL(您仍然可以在Reflector中执行),您会发现在赋值顺序和基本构造函数调用方面存在差异。
public class MyClass1
{
public MyObject MyObject = new MyObject();
}
public class MyClass2
{
public MyObject MyObject;
public MyClass2()
{
MyObject = new MyObject();
}
}
.class public auto ansi beforefieldinit test.MyClass1
extends [mscorlib]System.Object
{
.field public class test.MyObject MyObject
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// code size: 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void test.MyObject::.ctor()
IL_0006: stfld class test.MyObject test.MyClass1::MyObject
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: nop
IL_0012: ret
} // end of method MyClass1::.ctor
} // end of class test.MyClass1
.class public auto ansi beforefieldinit test.MyClass2
extends [mscorlib]System.Object
{
.field public class test.MyObject MyObject
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// code size: 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: newobj instance void test.MyObject::.ctor()
IL_000e: stfld class test.MyObject test.MyClass2::MyObject
IL_0013: nop
IL_0014: ret
} // end of method MyClass2::.ctor
} // end of class test.MyClass2