使用 属性 getter 进行初始化(以避免必须按特定顺序调用方法)是不好的做法吗?

Is using property getters for initialization (to avoid having to call methods in specific order) bad practice?

假设我有一个 class 为我的应用程序提供一些数据。数据最初来自数据库,我通过一些处理整个数据库事物的方法提供它,并将结果呈现为可用的 class 而不是原始查询结果。 class 必须进行一些设置(并不复杂)以确保调用的任何方法都可以使用数据库(例如连接到数据库,确保它包含一些关键信息等)。所以,如果我把它放在一个方法中(比如,方法 Init(),它将处理数据库检查、连接到它、验证它确实包含信息),我必须确保在之前调用这个方法任何其他方法。 所以,我通常会发现,而不是这样做:

public class DataProvider
{
    private SqlController controller;

    public void Init()
    {
        controller = new SqlController();
        controller.Init();
        controller.ConnectToDataBase();
        CheckForCriticalInfoInDatabase();
    }

    public Data GetData()
    {
        // get data from database (not actually going to use raw queries like that, just an example)
        var queryResult = sqlController.RunQuery("SELECT something FROM SOME_TABLE");
        // and present it as usable class
        Data usefulData = QueryResultToUsefulData(queryResult);
        return usefulData; 
    }

    ...
}

然后总是确保我在 GetData() 之前调用 Init(),我会做类似

的事情
    private SqlController _controller;

    private SqlController controller
    {
        get
        {
            if (_controller == null)
            {
                _controller = new SqlController();
                _controller.Init();
                _controller.ConnectToDataBase();
                CheckForCriticalInfoInDatabase();
            }
            return controller;
        }
    }

所以,现在我可以确定我不会使用未初始化的 SqlController,并且我不必在使用它的每个方法中都执行相同的空值检查。但是,我从来没有注意到在其他人的代码中以这种方式使用吸气剂。

有什么我没发现的陷阱吗?对我来说,它看起来与惰性初始化相同,不同的是我使用它不是因为初始化很重或很长,而是因为我不想检查我调用方法的顺序。 This question 指出它不是线程安全的(在我的情况下不是问题,而且我想它可以通过一些锁使其成为线程安全的)并且将 属性 设置为 null 会导致不直观行为(不用担心,因为我根本没有 setter 并且不应该以任何方式触及支持字段)。

此外,如果这种代码符合惯例,那么确保我的方法不依赖于它们被调用的顺序的正确方法是什么?

正如@madreflection 在 OP 评论中所说,对任何可能变慢的事情都使用一种方法。 getter 和 setter 应该只是获取和设置值的快速方法。

与 dbs 的连接可能很慢或无法连接,因此您可能设置了 catch 以尝试不同的连接方法等。

您还可以在对象的构造函数中进行检查,这样如果 init() 不在 运行 不同的函数中,就无法使用对象,从而节省了跟踪错误实际位置的时间正在发生。

例如,如果您有一个函数创建对象,执行一堆 'stuff' 然后尝试在没有 运行ning init() 的情况下使用该对象,那么在所有'stuff' 不是你创建对象的地方。这可能会让您认为您使用该对象的任何方式都有问题,而不是它尚未初始化。