基础的C#问题。
如何区分在声明时和在对象构造函数中创建类属性/字段实例的区别。例如:
public class MyClass
{
public MyObject = new MyObject();
}
对比
public class MyClass
{
public MyObject;
public MyCLass()
{
MyObject = new MyObject();
}
}
基础的C#问题。
如何区分在声明时和在对象构造函数中创建类属性/字段实例的区别。例如:
public class MyClass
{
public MyObject = new MyObject();
}
对比
public class MyClass
{
public MyObject;
public MyCLass()
{
MyObject = new MyObject();
}
}
如果一个字段有初始化器,那么它将在调用基类构造函数之前进行初始化,而如果初始化器在主体中,则该初始化程序仅在调用基类构造函数后执行。
如果基类构造函数调用虚方法,则这可能是相关的 - 但个人建议避免这种情况。
示例代码:
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#代码:
public class MyClass1
{
public MyObject MyObject = new MyObject();
}
public class MyClass2
{
public MyObject MyObject;
public MyClass2()
{
MyObject = new MyObject();
}
}
I got IL assembly:
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
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#中),字段的初始化赋值将发生在任何基类构造函数的调用之前(如 this question 中所证明的,关于 VB 是否可以被强制执行相同的操作)。
这意味着您不能使用初始化器语法来引用基类的字段(即,您无法直接将此VB转换为C#):
Public Class Base
Protected I As Int32 = 4
End Class
Public Class Class2
Inherits Base
Public J As Int32 = I * 10
End Class
MyObject = new MyObject()
不是初始化器,而只是一个赋值语句。在C#中,初始化器具有特定的含义。 - Damien_The_Unbeliever