我最近一直在用c#和Java编程,我很好奇初始化我的类字段的最佳位置在哪里。

我应该在申报时申报吗?:

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

或者在构造函数中?:

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

我很好奇你们这些老兵认为最好的做法是什么。我想保持一致,坚持一种方法。


当前回答

我认为有一个警告。我曾经犯过这样一个错误:在派生类内部,我试图“初始化at声明”从抽象基类继承的字段。结果是存在两组字段,一组是“base”字段,另一组是新声明的字段,这花费了我相当多的时间来调试。

教训:要初始化继承的字段,需要在构造函数内部进行。

其他回答

当你不需要一些逻辑或错误处理时:

在声明时初始化类字段

当你需要一些逻辑或错误处理时:

在构造函数中初始化类字段

当初始化值可用时,这工作得很好 初始化可以放在一行上。然而,这种形式 初始化因为简单而有局限性。如果 初始化需要一些逻辑(例如,错误处理或 对于循环填充复杂数组),简单的赋值是不够的。 实例变量可以在构造函数中初始化,其中error 可以使用处理或其他逻辑。

来自https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html。

在声明中设置值会略微提高性能。如果你在构造函数中设置它,它实际上被设置了两次(第一次为默认值,然后在ctor中重置)。

我的规则:

不要初始化声明中的默认值(null, false, 0, 0.0…) 如果没有改变字段值的构造函数形参,最好在声明中初始化。 如果字段的值因构造函数形参而改变,则将初始化放在构造函数中。 坚持练习(这是最重要的规则)。

c#的设计表明,内联初始化是首选,否则就不会出现在语言中。只要可以避免代码中不同位置之间的交叉引用,通常情况下就会更好。

还有与静态字段初始化的一致性问题,需要内联以获得最佳性能。构造函数设计框架设计指南是这样说的:

考虑内联初始化静态字段,而不是显式使用静态构造函数,因为运行时能够优化没有显式定义静态构造函数的类型的性能。

“考虑”在这里的意思是除非有很好的理由不这样做。对于静态初始化字段,一个很好的理由是初始化太复杂,不能内联编码。

“更喜欢在声明中初始化”,似乎是一个很好的一般实践。

这里是一个不能在声明中初始化的例子,所以它必须在构造函数中完成。 错误CS0236字段初始化器不能引用非静态字段、方法或属性

class UserViewModel
{
    // Cannot be set here
    public ICommand UpdateCommad { get; private set; }

    public UserViewModel()
    {
        UpdateCommad = new GenericCommand(Update_Method); // <== THIS WORKS
    }

    void Update_Method(object? parameter) 
    {
    }
}