简体   繁体   English

获取字段的默认值

[英]Get default value of a field

I am wondering how to get the default value of a field of any arbitrary class. 我想知道如何获取任意类的字段的默认值。

For example, 例如,

public class Example
{
    public int a = 10;
}

I want to get the value 10 when only typeof(Example) is given. 当仅给出typeof(Example)时,我想获取值10

This default value is useful because I am writing a function to create a non-null default instance for any type. 这个默认值很有用,因为我正在编写一个函数来为任何类型创建一个非空的默认实例。 It would be nice to have the instance initialized to the values given in the declaration. 最好将实例初始化为声明中给定的值。

Please note that creating an instance through a default constructor and grab the value is not an option to me because I hope the function I am working on can be applied to classes with or without default constructors. 请注意,通过默认构造函数创建实例并获取值不是我的选择,因为我希望正在使用的函数可以应用于带有或不带有默认构造函数的类。

Also, DefaultValueAttribute is not an option for me either. 另外, DefaultValueAttribute也不是我的选择。 As far as I know, attributes can only take several types as its argument. 据我所知,属性只能采用几种类型作为其参数。 So I cannot get the default value of fields of self-defined types. 因此,我无法获得自定义类型的字段的默认值。

Edit 1: 编辑1:

I know this question seems to be a duplication of Get default value of class member , but it is not. 我知道这个问题似乎是Class成员Get default value的重复,但事实并非如此。 In the referenced question, the OP is satisfied with using constructor to get a real instance of the class. 在引用的问题中,OP对使用构造函数获取类的真实实例感到满意。 But in my case, I cannot be sure that a default constructor exists for the class I am dealing with. 但就我而言,我不确定要处理的类是否存在默认构造函数。

I am writing a default value generator because I need a fake object of an arbitrary type. 我正在编写一个默认值生成器,因为我需要一个任意类型的伪造对象。 That is, there is no assumption made of how the type is going to be. 也就是说,没有假设类型会是什么样。 The fake object will be inspected through a GUI, and a user can edit the values of fields that are exposed in the inspector. 伪对象将通过GUI进行检查,并且用户可以编辑在检查器中公开的字段的值。 Here the arbitrary type is important to me because the inspector should work on not only types defined by me but also on types defined in libraries. 在这里, 任意类型对我很重要,因为检查员不仅应处理我定义的类型,还应处理库中定义的类型。 Moreover, the fake object should never be null or the inspector will blow up, LOL. 而且,伪造的对象永远不能为空,否则检查员会崩溃,大声笑。

FormatterServices.GetSafeUninitializedObject gets me an acceptable fake object as it allocates memory blocks and initialize them to zeros. FormatterServices.GetSafeUninitializedObject我分配了一个可接受的伪对象,因为它分配了内存块并将其初始化为零。 But I feel like it would be better if the fake object can be further initialized so the fields can have their default values shown in the inspector. 但是我觉得最好进一步初始化假对象,以便字段可以在检查器中显示其默认值。

Thanks to Patrick Hofman reminds me that the "default value" I am talking about is not the real default but a expression that will be evaluated in constructors. 感谢Patrick Hofman提醒我,我所说的“默认值”不是真正的默认值,而是将在构造函数中求值的表达式。 That being said, I am still wondering if it is possible to fetch the field initialization expression and event evaluate it. 话虽如此,我仍然想知道是否有可能获取字段初始化表达式并对其进行事件评估。

I think there should be a way of doing it because decompilers such as ILSpy can shows the field initializer in the decompiled results. 我认为应该有一种方法,因为像ILSpy这样的反编译器可以在反编译结果中显示字段初始化程序。

You can only get values of constants, not any other type of variables, since they need to have an initialized class to retrieve a value from, which aren't real defaults any more, just the current value. 您只能获取常量的值,而不能获取任何其他类型的变量,因为它们需要一个初始化的类来从中检索值,而不再是真正的默认值,而只是当前值。

The previously duplicate Get default value of class member tells what to do if you drop the don't create an instance constraint. 先前重复的“ 获取类成员的默认值”会告诉您,如果删除“ 不创建实例约束”,该怎么办

What about this one? 这个如何?

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

Can you tell me what the default value of this field is? 您能告诉我此字段的默认值是什么吗? Even if you could, it isn't really the default value, it is the evaluated value of a certain variable in a point-in-time. 即使可以,它实际上并不是默认值,而是某个时间点某个变量的评估值。

You can inspect the IL code, and look for members called .ctor (these are the instance constructors). 您可以检查IL代码,并查找名为.ctor成员(这些是实例构造函数)。

Then find one which does not call another Example::.ctor overload, but calls instead a base-class constructor, in your case [mscorlib]System.Object::.ctor() . 然后找到一个不会 call另一个Example::.ctor重载,而是调用基类构造函数的实例,在您的情况下为[mscorlib]System.Object::.ctor() (If there does not exist one, the instance field initializers are unreachable (pathological case)!) (如果不存在,则实例字段初始化器将无法访问(病理情况)!)

Then, inside the IL of this member, the field assignments stfld that come before the call to the base class .ctor , are the field initializers. 然后,在此成员的IL中,调用基类.ctor 之前的字段分配stfld是字段初始化程序。 Voilà! 瞧!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM