[C#]Formのデザイナがエラーを吐いた時の対処

私はC#が好きだが、Windows Formsは嫌いだ。わかりにくくて大量にあるイベント、貧弱なBinding、同世代のADO.NETの関連ライブラリ(DataSet, DataTable)が貧弱過ぎる。など。

でも業務アプリだとまだまだ現役で使うことが多いだろう。そういう時に、FormをVisual Studioのデザイナで作業していると、突然、「デザイナを開く時にエラーが発生しました」などというメッセージが現れ、せっかく時間をかけて作ったフォームが開けなくなったりしてしまう。こうならないために、頻繁なバックアップは欠かせないが、結構このようなエラーが出る頻度が高いため、何度も何度も後戻りになるのは辛いだろう。なので、ここでは対処方法の手助けとなるヒントを挙げたい。

原因はなにか

私の経験からすると、ほぼ間違いなく、プログラマが打ったコードに原因がある。スタックトレースが表示されていれば分かりやすいかも知れない。よくよく内容を読み、ユーザー(プログラマ)が書いたコードがあれば、そこに原因があることが多い。

例1:デザイナから実行されることを想定していないコードがある

たとえば、コンストラクタで何かのオブジェクトAを引数として受け取り、LoadイベントでAのメソッドを実行する、なんてコードを書くと、そこでNullReferenceExceptionが発生する。これは、デザイナが起動するときは引数なしのコンストラクタを暗黙的に読んでいるからだ。その後、デザイナを開く時にLoadイベントもちゃんと飛んでしまうらしく、だから、エラーになる。

このような場合は、Loadイベントで実行されるコードにおいて、FormのDesignModeプロパティ(Control.DesignMode)がTrueであるならば何もしない、などの条件分岐を入れると改善する。(余談だが、とても醜いコードだと思う。他にやりようが無かったのだろうか)

例2:デザイナで貼り付けている他のユーザー定義コントロールなどにバグがある

原因が、デザイナで開けないフォームそのものにあるとは限らない。そのフォームで使用している、UserControlを継承したなにかのコントロールや、ComboBox、TextBoxなどを継承したコントロールにバグがあっても、デザイナでフォームが開けないことがある。特に、デザイナが触るのは引数なしのコンストラクタやプロパティあたりなので、そのあたりをよく見るとバグが潜んでいるかもしれない。

たとえば、私はミスタイプにより、プロパティにアクセスすると無限ループからStackOverflowExceptionが発生してしまうようなコードを書いたことがある。その状態でデザイナを開くと、スタックトレースすら表示されず、いきなりVisual Studioが強制終了してしまった。こうなると何も情報が得られないため、原因解明にとても手こずる。

例3:よく分からないけど色々やってたら直った

このパターンが一番困るのだが、私の経験上、よくある。とりあえず、バックアップを取った後にダメ元で以下をやってみよう。

  • 一度クリーンしてからビルドしてみる
  • Visual Studioを再起動してみる
  • Designer.csを直接編集して、怪しい行をコメントアウトしてみる
  • 他のFormが開けるかどうか試してみる

ちなみに、Formを継承していて、かつ、デザイナが生成するInitializeComponent()メソッドが2回呼ばれているかのようなエラーが出た時は、クリーン&ビルド&VS再起動が効く場合が多い気がする。

それでもダメなら

上記のようなことをやれば大体直ると思われるが、あまりにも長い時間悩むようであれば、スパッと諦め、前にとったバックアップから復元するしか無いだろう。バックアップを取っていなかったら、もう最初から頑張って作り直し、次回から定期的にバックアップとか、可能であれば頻繁にリポジトリにコミットするとか、そういうふうに心がけましょう。

ちなみに

私は毎回Windows Forms系の記事を書く時、以下の様なことを付け加えています。

やっぱりどう考えてもWindows FormsとDataSet、DataTableなどを組み合わせて作るのは生産性が低く、かつ、上記のような目に遭うことが多い。WPF+Entity Framework(POCO)に切り替えてMVVMによる開発をすべき。WPF+Entity Frameworkは後発の技術でほとんどの面でWinFormsより優れているし、XMLによるGUIの記述方法はWPFに限らず、他の多くのGUIアプリ開発でも利用されている標準的な方法である。WinFormsに未来は無いが、WPFを覚えていたら他の技術に乗り換えるときにも知識を応用できる。さっさとWPFに切り替えよう。