【问题标题】:Get default value of a field获取字段的默认值
【发布时间】:2015-09-29 01:53:50
【问题描述】:

我想知道如何获取任意类的字段的默认值。

例如,

public class Example
{
    public int a = 10;
}

当只给出typeof(Example) 时,我想获得10 的值。

这个默认值很有用,因为我正在编写一个函数来为任何类型创建一个非空默认实例。将实例初始化为声明中给出的值会很好。

请注意,通过默认构造函数创建实例并获取值不是我的选择,因为我希望我正在处理的函数可以应用于有或没有默认构造函数的类。

另外,DefaultValueAttribute 也不适合我。据我所知,属性只能以几种类型作为其参数。所以无法获取自定义类型字段的默认值。

编辑 1:

我知道这个问题似乎与Get default value of class member 重复,但事实并非如此。在引用的问题中,OP 对使用构造函数获取类的真实实例感到满意。但就我而言,我无法确定我正在处理的类是否存在默认构造函数。

我正在编写一个默认值生成器,因为我需要一个 任意 类型的假对象。也就是说,没有假设类型将如何。假对象将通过 GUI 进行检查,用户可以编辑在检查器中公开的字段的值。这里 arbitrary 类型对我来说很重要,因为检查器不仅应该处理我定义的类型,还应该处理库中定义的类型。此外,假对象永远不应该为空,否则检查员会炸毁,哈哈。

FormatterServices.GetSafeUninitializedObject 给我一个可接受的假对象,因为它分配内存块并将它们初始化为零。但我觉得如果可以进一步初始化假对象会更好,以便字段可以在检查器中显示其默认值。

感谢 Patrick Hofman 提醒我,我所说的“默认值”不是真正的默认值,而是将在构造函数中计算的表达式。话虽如此,我仍然想知道是否可以获取字段初始化表达式并对其进行事件评估。

我认为应该有办法做到这一点,因为 ILSpy 等反编译器可以在反编译结果中显示字段初始值设定项。

【问题讨论】:

  • 如果类型的构造函数分配了另一个值怎么办?那么你的“默认”值是没有意义的。
  • 你能用 (new Example()).a 吗?
  • 如果不创建类型的实例或依赖于属性等元数据,就没有明智的方法。
  • 如果没有像重复问题中那样初始化这种类型,就无法获得这个值,因为编译过程会将这个值赋值插入到构造函数中。
  • 纯粹出于好奇,我问这个问题——但为什么呢?你为什么要这样做?有什么要求? (真正感兴趣)。

标签: c#


【解决方案1】:

您只能获取常量的值,而不能获取任何其他类型的变量,因为它们需要有一个初始化的类来从中检索值,这不再是真正的默认值,只是当前值。

先前重复的Get default value of class member 告诉您如果放弃不创建实例约束该怎么办。

这个呢?

public class Example
{
    public readonly DateTime a = DateTime.Now;
}

你能告诉我这个字段的默认值是什么吗?即使可以,它也不是真正的默认值,它是某个变量在某个时间点的评估值。

【讨论】:

  • 最后一个例子中默认是09/28/2015 16:07:08,不等待09/28/2015 16:07:20,不等待09/28/2015 16:07:23...
  • 你成功了! @Jeppe
【解决方案2】:

您可以检查 IL 代码,并查找名为 .ctor 的成员(这些是实例构造函数)。

然后找到一个 call 另一个Example::.ctor 重载,而是调用基类构造函数,在您的情况下为[mscorlib]System.Object::.ctor()。 (如果不存在,则实例字段初始值设定项无法访问(病态情况)!)

然后,在该成员的 IL 中,在调用基类 .ctor 之前 的字段分配 stfld 是字段初始值设定项。瞧!

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 2012-10-24
    • 1970-01-01
    • 2022-01-07
    • 2010-11-21
    • 2014-09-28
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多