データベースに依存しないカーソル アクションの抽象クラスがあります。そこから派生して、データベース固有のものを処理するための抽象メソッドを実装するクラスがあります。
問題は、基本クラスの 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()
作成します。これは、クラスから省略された多くのメソッドが正しく機能するために最も重要です。ctor が戻ったときにクラスが一貫した状態になるようにするには、ベース ctor で呼び出す必要があります。これを反映するために、上記のコードを少し更新しました。
CreateCursor()