c# - 您能检测到 C# 字段是否已分配默认值吗?

标签 c# reflection default

假设您有一个类声明,例如:


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.7stfld 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/

相关文章:

c# - Visual Studio 2010 : How to set build platform to Active(x86)?

sql - SQL Server 将空值插入非空列时如何设置默认值?

c# - 如何将通过反射获得的对象传递给模板?

iis-7 - DefaultDocument 突然无法在 IIS7 上运行

C switch case default 总是执行

c# - 在放置或移除 key 时获取 USB 唯一 ID

c# - 实习生字符串文字误解?

c# - 列出哪些指数可以向两个方向扩展?

swift - 如何反射(reflect) NSManagedObject 的非托管属性

Java - 获取封闭实例