首先解释一下内联初始化的内联的意思:就是在声明字段的时候同时进行初始化赋值。
举个简单的例子就是:
class SomeType()
{
int x = 5;
}
这里为x赋值为5实际上发生在SomeType的构造器中,IL代码可以作证:
SomeType的构造函数的IL代码如下:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 14 (0xe)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: ret
} // end of method SomeType::.ctor
instance void .ctor() cil managed
{
// 代码大小 14 (0xe)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: ret
} // end of method SomeType::.ctor
我们可以看到确实如此。
所以说内联初始化字段只是C#提供的一种简化语法,但是往往会造成代码的膨胀。
比如说:
class SomeType
{
int x = 5;
string s = "Hi there";
double d = 3.14159;
byte b;
public SomeType()
{}
public SomeType(int x)
{
}
public SomeType(string s)
{
}
}
{
int x = 5;
string s = "Hi there";
double d = 3.14159;
byte b;
public SomeType()
{}
public SomeType(int x)
{
}
public SomeType(string s)
{
}
}
编译以后查看IL代码:
其中有三个构造函数:
.ctor : void(int32)的代码为:
.method public hidebysig specialname rtspecialname
instance void .ctor(int32 x) cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
instance void .ctor(int32 x) cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
.ctor : void(string)的IL代码:
.method public hidebysig specialname rtspecialname
instance void .ctor(string s) cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
instance void .ctor(string s) cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
.ctor : void()的IL代码为:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
instance void .ctor() cil managed
{
// 代码大小 40 (0x28)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 SomeType::x
IL_0007: ldarg.0
IL_0008: ldstr "Hi there"
IL_000d: stfld string SomeType::s
IL_0012: ldarg.0
IL_0013: ldc.r8 3.1415899999999999
IL_001c: stfld float64 SomeType::d
IL_0021: ldarg.0
IL_0022: call instance void [mscorlib]System.Object::.ctor()
IL_0027: ret
} // end of method SomeType::.ctor
这回清楚了吧,三个构造函数初始化了三次。所以最好避免在声明的时候初始化字段,而放在构造其中去进行,这样有助于减小代码尺寸,所以我们改写如下(假设每个构造器都需要初始化这些字段):
class SomeType
{
int x;
string s;
double d;
byte b;
public SomeType()
{
x = 5;
s = "Hi there";
d = 3.14159;
}
public SomeType(int x) : this()
{
this.x = x;
}
public SomeType(string s) : this()
{
this.s = s;
}
}
{
int x;
string s;
double d;
byte b;
public SomeType()
{
x = 5;
s = "Hi there";
d = 3.14159;
}
public SomeType(int x) : this()
{
this.x = x;
}
public SomeType(string s) : this()
{
this.s = s;
}
}
我们把公共的初始化代码放到默认构造器中,其他的构造器都先调用默认构造器就达到了我们的目的。