假设您有一个类声明,例如:
class MyClass
{
int myInt=7;
int myOtherInt;
}
现在,在通用代码中有没有一种方法,使用反射(或任何其他方式,就此而言),我可以推断出 myInt 已分配默认值,而 myOtherInt 没有? 请注意使用显式默认值初始化和保留其隐式默认值之间的区别(默认情况下,myOtherInt 将初始化为 0)。
根据我自己的研究,似乎没有办法做到这一点 - 但我想在放弃之前先在这里问一下。
[编辑]
即使是可空类型和引用类型,我也想区分保留为空的类型和明确初始化为空的类型。这样我就可以说带有初始化程序的字段是“可选的”,而其他字段是“强制性的”。目前我不得不使用属性来做到这一点——在这种情况下,这让我对它们的信息冗余感到恼火。
最佳答案
我编译了你的代码并将其加载到 ILDASM 中并得到了这个
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.7
IL_0002: stfld int32 dummyCSharp.MyClass::myInt
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: nop
IL_000e: ret
} // end of method MyClass::.ctor
注意 ldc.i4.7
和 stfld int32 dummyCSharp.MyClass::myInt
似乎是设置 myInt 字段默认值的说明。
所以这样的赋值实际上被编译为构造函数中的附加赋值语句。
要检测这样的赋值,那么您将需要反射以反射(reflect) MyClass 的构造函数方法的 IL 并查找 stfld
(设置字段?)命令。
编辑:如果我明确地在构造函数中添加一些赋值:
class MyClass
{
public int myInt = 7;
public int myOtherInt;
public MyClass()
{
myOtherInt = 8;
}
}
当我在 ILDASM 中加载它时,我得到了这个:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.7
IL_0002: stfld int32 dummyCSharp.MyClass::myInt
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: nop
IL_000e: nop
IL_000f: ldarg.0
IL_0010: ldc.i4.8
IL_0011: stfld int32 dummyCSharp.MyClass::myOtherInt
IL_0016: nop
IL_0017: ret
} // end of method MyClass::.ctor
请注意,我添加的对 myOtherInt 的额外赋值是在调用 Object 类的构造函数之后添加的。
IL_0008: call instance void [mscorlib]System.Object::.ctor()
原来如此,
在 IL 中调用 Object 类的构造函数之前完成的任何赋值都是默认值赋值。
它后面的任何内容都是类的实际构造函数代码中的语句。
但是应该进行更广泛的测试。
附注那很有趣 :-)
关于c# - 您能检测到 C# 字段是否已分配默认值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/271904/