という問題にこの間半日ほど悩んだので、原因と対処法をば...
ケース1:こんなの
public abstract class BaseForm : Form
{
public abstract void hoge();
}
public class DerivedForm : BaseForm
{
public override void hoge() { /* なにやら */ }
}
ケース2:こんなの
public class BaseForm : Form
{
public BaseForm()
{
this.Load += new System.EventHandler(this.FormLoad);
}
private void FormLoad(object sender, System.EventArgs e)
{
throw new Exception("hoge");
}
}
public class DerivedForm : BaseForm
{
}
ケース1の原因と対処法
原因:多分どのIDE(VS2003でなくても)でもそのものずばりの理由がエラーメッセージに出てると思う。継承フォームをデザインモードで表示するために、基底FormをnewしてShowする必要があるけど、abstract classだからnewできないそうな。
対策:基底Formをabstract class にするのはやめませう。templateパターンを使いたい場合はMVCパターンに則って、template部分を別途Controllerとして切り分けるのがいいと思うよ。
// コントローラ
public abstract class BaseController
{
public abstract void hoge();
}
public class DerivedController
{
public abstract void hoge() { /* なにやら */ }
}
// ビュー
public class BaseForm : Form
{
private BaseController contoller;
protected BaseController Controller
{
set { controller = value; }
}
public void foo()
{
controller.hoge();
}
}
public class DerivedForm : BaseForm
{
public DerivedForm()
{
// 必要なContollerを設定 (※BaseFormのコンストラクタ内では使えないので注意)
Controller = new DerivedController();
}
}
基底Formに implements 何やらをくっつけて実装しないっても同じことなので止めよう。
virtual methodにしておいて基底Formの方では/NotImplementedExceptionを投げるという方法も無いことは無いけど。コンパイル時に未実装が検出できないのはダサいよね
その2の原因と対処法
原因:基底FormのLoadイベントの中で例外が発生して外に抜けてきた。(上の例では明示的にthrow new Exceptionしてるけど、普通はNullReferenceExceptionとかがどこからともなく発生してくる。
newしてからShowするまでの間に何かpropertyを設定しなきゃいけないだとか、アプリ動作時に動的に設定を得るだとかしている場合が危ない。
対策:Component.DesignMode property をチェックして、DesignMode時はLoadイベントをskipする。
public class BaseForm : Form
{
public BaseForm()
{
this.Load += new System.EventHandler(this.FormLoad);
}
private void FormLoad(object sender, System.EventArgs e)
{
// 華麗にスルー
if (DesignMode) return;
throw new Exception("hoge");
}
}





コメントする