构造函数中的 C# 虚拟方法调用 - 如何重构?

标签 c# .net

我有一个抽象类,用于与数据库无关的游标操作。 从那里派生出,有一些类实现了处理特定于数据库的东西的抽象方法。

问题是,基类ctor需要调用一个抽象方法——当ctor被调用时,它需要初始化特定于数据库的游标。

我知道为什么不应该这样做,我不需要那个解释!

这是我的第一个实现,显然行不通 - 这是教科书上的“错误方式”。 重写的方法访问派生类中的一个字段,该派生类尚未实例化:

public abstract class CursorReader
{
    private readonly int m_rowCount;
    protected CursorReader(string sqlCmd)
    {
         m_rowCount = CreateCursor(sqlCmd); //virtual call !
    }
    protected abstract int CreateCursor(string sqlCmd);

    //...other (non-abstract) methods that assume a cursor exists
}

public class SqlCursorReader : CursorReader
{
    private SqlConnection m_sqlConnection;

    public SqlCursorReader(string sqlCmd, SqlConnection sqlConnection)
    {
        m_sqlConnection = sqlConnection;     //field initialized here
    }
    protected override int CreateCursor(string sqlCmd)
    {
        //uses not-yet-initialized member *m_sqlConnection*
        //so this throws a NullReferenceException
        var cursor = new SqlCursor(sqlCmd, m_sqlConnection); 
        cursor.Create();
        return cursor.Count();
    }
}

我会跟进一个关于我尝试解决这个问题的答案......

更新

重写方法 CreateCursor() 在数据库中创建一个实际 游标。这对于类中省略的许多方法的正确运行至关重要。
CreateCursor() 必须在基本 ctor 中调用,以便类在 ctor 返回时处于一致状态。我稍微更新了上面的代码以反射(reflect)这一点。

最佳答案

你总是可以有一个惰性属性来获取计数。

public abstract class CursorReader
{
    private int? m_rowCount;
    protected CursorReader()
    {

    }
    protected abstract int CreateCursor(string sqlCmd);
    protected int RowCount {
      get {
          if (m_RowCount == null)
          {
             m_RowCount = CreateCursor(sql);
          }
          return m_RowCount.Value;
      }

    }
}

关于构造函数中的 C# 虚拟方法调用 - 如何重构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711752/

相关文章:

c# - 如何编写 MySql 连接字符串的示例有哪些?

.net - 如果Unity不在GAC中,VS如何知道在添加引用中显示它?

c# - C#中比较不同时区时间的代码示例

c# - 获取 DataTable 列数据类型

c# - DHTMLX 网格 : Populate cells with dropdown menu

c# - 异步内存流处理方法 : which of the following?

c# - 将位图图像转换为字节数组

c# - 我怎样才能最好地按需生成随机数的静态数组?

c# - 如何从 Protocol Buffers .NET 代码生成 .proto 文件?

c# - LINQ 查询除了不起作用,List<long?> 与 List<long>