假设你有一个类声明,例如:
class MyClass { int myInt=7; int myOtherInt; }
现在,在通用代码中是否有一种方法,使用反射(或任何其他方法),我可以推断myInt已分配默认值,而myOtherInt则没有?注意用显式默认值初始化和保留默认值的默认值之间的区别(myOtherInt默认初始化为0).
根据我自己的研究,看起来没有办法做到这一点 - 但我想在放弃之前我会问这里.
[编辑]
即使有可空和引用类型,我也希望在那些保留为null的那些和已经显式初始化为null的那些之间进行distingush.这样我可以说具有初始化的字段是"可选的"而其他字段是"强制的".目前我不得不使用属性来做这件事 - 在这种情况下,这会让我感到信息冗余.
我编译了你的代码并在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字段设置默认值的说明.
因此,这样的赋值实际上被编译为构造函数中的附加赋值语句.
要检测这样的赋值,那么你需要反射来反映MyClass的构造函数方法的IL并查找stfld
(set fields?)命令.
编辑:如果我明确地将一些赋值添加到构造函数中:
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类的构造函数之前完成的任何赋值都是默认值赋值.
跟随它的任何内容都是类的实际构造函数代码中的语句.
但是应该进行更广泛的测试.
ps很有趣:-)