如何在从构造函数调用的initialize方法中设置只读字段?

Ben*_*son 36 c# constructor readonly

我确定我已经在某处找到了我可以通过使用我的Init()方法之上的属性来执行以下操作,该方法告诉编译器必须只从构造函数调用Init()方法,从而允许readonly字段被设定.我忘记了该属性的调用,但我似乎无法在谷歌上找到它.

public class Class
{
    private readonly int readonlyField;

    public Class()
    {
        Init();
    }

    // Attribute here that tells the compiler that this method must be called only from a constructor
    private void Init()
    {
        readonlyField = 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*Tao 42

在我的书中,Rob的答案就是这样做的方法.如果需要初始化多个字段,可以使用out参数来完成:

public class Class
{
    private readonly int readonlyField1;
    private readonly int readonlyField2;

    public Class()
    {
        Init(out readonlyField1, out readonlyField2);
    }

    protected virtual void Init(out int field1, out int field2)
    {
        field1 = 1;
        field2 = 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

我个人认为这在某些情况下是有意义的,例如当你想要你的字段时,readonly希望能够在派生类中以不同方式设置它们(而不必通过某些protected构造函数链接大量参数).但也许那只是我.

  • @Derar:该死的,伙计......我认为反思绝对不是*这样做的方式.当所有代码都在你面前时,为什么要在自己的类中使用反射? (5认同)
  • 出参数,yuk! (3认同)
  • @Chuck:嘿,我从来没有说过它很漂亮。 (2认同)

tvt*_*173 13

而不是使用Initialize方法,如何通过所有其他构造函数继承基本构造函数.即

public class MyClass
{
    readonly int field1;
    readonly double field2;
    public MyClass(int field1, double field2)
    {
        //put whatever initialization logic you need here...
        field1 = 10;
        field2 = 30.2;
    }
    public MyClass(int field1, double field2p1, double field2p2)
        : this(field1, (field2p1 + field2p2))
    {
        //put anything extra in here
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能有点晚到达有需要的原始人,但似乎这将彻底解决问题......无需使用任何讨厌的反射或输出参数.

  • 这绝对是在构造函数之间共享代码的更聪明的方法。 (2认同)

Rob*_*Rob 12

我能想到的唯一解决方案是从需要分配字段的Init()方法返回值readonly:

public class Class
{
    private readonly int readonlyField;

    public Class()
    {
        readonlyField = Init();
    }

    private int Init()
    {
        return 1;
    }
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*Par 6

这是不可能做到的.标记的字段readonly只能从构造函数中设置


Ani*_*Ani 5

贾里德是对的; 这是不可能的.我能想到的解决方法是:

  1. 初始化声明中的字段.
  2. 在构造函数中初始化字段(手动内联您的Init方法).
  3. 将字段分配给方法返回的值,例如: _myField = GetInitialMyFieldValue();
  4. Init使用out修改器将字段传递给方法.如果要初始化许多字段,这可能很有用,这些字段依赖于构造函数参数.例如

 private readonly int _x;
 private readonly string _y;

 private void Init(int someConstructorParam, out int x, out string y){ .. }

 public Class(int someConstructorParam)
 {
     Init(someConstructorParam, out _x, out _y);
 } 
Run Code Online (Sandbox Code Playgroud)