问题描述
假设您有一个类声明,例如:
Say you have a class declaration, e.g.:
class MyClass
{
int myInt=7;
int myOtherInt;
}
现在,在通用代码中是否有一种方法可以使用反射(或其他方法)意思是说),我可以推断出myInt已分配了默认值,而myOtherInt没有?
请注意,使用显式默认值初始化与保留为隐式默认值(默认情况下,myOtherInt将被初始化为0)之间的区别。
Now, is there a way in generic code, using reflection (or any other means, for that matter), that I can deduce that myInt has a default value assigned, whereas myOtherInt does not?Note the difference between being initialised with an explicit default value, and being left to it's implicit default value (myOtherInt will be initialised to 0, by default).
从我自己的研究来看,似乎没有办法做到这一点-但我想我会在放弃之前先问一下。
From my own research it looks like there is no way to do this - but I thought I'd ask here before giving up.
即使是具有可为空的类型和引用类型,我也想在那些留为null的类型和那些显式初始化为null的类型之间进行区分。这样,我可以说带有初始化程序的字段是可选的,而其他字段是强制性的。目前,我必须使用属性来执行此操作-在这种情况下,这会干扰我的信息冗余。
Even with nullable and reference types I want to distingush between those that have been left as null, and those that have been explicitly initialised to null. This is so that I can say that fields with an initialiser are "optional" and other fields are "mandatory". At the moment I'm having to do this using attributes - which niggles me with their redundancy of information in this case.
推荐答案
我编译了您的代码,并将其加载到ILDASM中,并得到了这个
I compiled your code and load it up in ILDASM and got this
.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
似乎是设置
因此,这样的分配实际上是作为附加项编译的。 l构造函数中的赋值语句。
要检测到这种赋值,则需要进行反思以反映MyClass的构造函数方法的IL并寻找 stfld
(设置字段?)命令。
To detect such assignment, then you will need reflection to reflect on the IL of MyClass's constructor method and look for stfld
(set fields?) commands.
编辑:如果我添加
class MyClass
{
public int myInt = 7;
public int myOtherInt;
public MyClass()
{
myOtherInt = 8;
}
}
当我将其加载到ILDASM中时,得到了这个:
When I load it up in ILDASM, I got this:
.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类的构造函数。
Note that the extra assigment on myOtherInt that I added was addded after a call the Object class's constructor.
IL_0008: call instance void [mscorlib]System.Object::.ctor()
所以有,
在IL中对对象类的构造函数的调用之前 完成的所有赋值都是默认值赋值。
Any assignment done before the call to Object class's constructor in IL is a default value assignment.
紧随其后的是该类的实际构造函数代码中的一条语句。
Anything following it is a statement inside the class's actual constructor code.
不过,应该进行更广泛的测试。
More extensive test should be done though.
ps很好玩:-)
这篇关于是否可以检测C#字段是否已分配默认值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!