我有一个抽象类,用于与数据库无关的游标操作。 从那里派生出,有一些类实现了处理特定于数据库的东西的抽象方法。
问题是,基类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/