【C# WPF】WPFを理解したいC#初心者の話【MVVMパターン編その5】

C# WPFについて学んでいく過程を備忘録として残して置きたいと思います。

1. 前回の問題点を考える


前回は、電卓アプリケーションのボタン部分をコマンドを作成してバインドして、実際に実装してみました。

しかし、ボタンを押すと例外処理が走ってしまい、アプリケーションの動作が停止してしまいました。

今回はそうなってしまった原因を探るところから始めていきます。

2. 動作が停止してしまった原因を探る

開発において、エラーやバグとの戦いはつきものです。

今回はエラーなので、まずは表示されたエラーメッセージをよく見てみたいと思います。


表示されていたエラーの内容はこちらです。

こういうメッセージは英語で書かれていることが多いですが、基本的に簡潔でそれほど難しいことは書かれないはずなので、頑張って読み解いていきます。


内容としては、Nullのオブジェクトの参照をしてしまった場合に起きる例外処理に引っ掛かりましたよ、ということでしょうか。

こういうエラーメッセージが発生したタイミングでは、コードの実行も一時停止している事が多いので、止まっている部分が問題の箇所です。

        public void Execute(object parameter)
        {
            string temp = ((Button)parameter).Name;
            m_vm.ValueButton_Command(temp);
        }

コマンド処理の中の実行の処理を行う「Execute」の中でボタンのプロパティが取得できそうな気がしたのですが、このままではダメなようです。

Executeの引数であるobject型のparameterがコマンド処理を発生させたコントロールのプロパティを持っていそうだったのですが、どうやらここはNullで処理を行うようですね。


NullのオブジェクトをButtonのコントロールとして見て、そのButtonの名前を取得しようとしたので、そのオブジェクトはNullだからそのまま参照すると危険ですよ、という感じで例外処理が走ったのでしょう。


つまり、ここを作り変えてparameterにコントロールのプロパティが入っている状態にするか、そもそもここその処理を行うべきではないのかを考える必要が出てきました。

3. 例外処理とNullとは?


まずは先ほどからよく出てくる「例外処理」について少し深堀りして解説します。

例外処理とは、システムの設計で想定されていない動作でありユーザーの操作によって解決出来ない問題に対して対処をするための処理のことです。

システムの設計で想定されていない動作や問題の例をいくつか挙げてみます。

・ハードウェアの故障

・システムの設定ミス

・ユーザーに入力を行わせる処理での入力間違い

・実行してはいけない演算

・割り当てられていない記憶領域へのアクセス


ハードウェアの故障は一番想像しやすいと思います。

システムやアプリケーションの設計開発を行う際に、それらを使用するためのハードウェアが故障していることを想定して作業を行うことは基本的にありません。


さらに言えば、ハードウェアの故障と一言にいってもその原因は数え切れません。

それらすべてを網羅して想定しながら開発を行うとなれば、開発のコストは跳ね上がります。

ここで例外処理の出番です。


システムの設定ミスは、使用環境に搭載されたOSと開発時に想定していたOSが異なる、あるいはディレクトリの参照先や保存先、その他設定値で想定されていないミスが発生している状況が想像しやすいかもしれません。


ユーザーに入力を行わせる処理での入力間違いは、今回開発している電卓アプリケーションの最初の設計でも少し触れました。

ユーザーがテキスト入力を行うようなコントロールに対して、例えばそれが半角英数字で入力してほしいモノだった場合に全角入力されてしまった、というような状況です。


実行してはいけない演算も一部触れました。一番有名なのは「ゼロ除算」と呼ばれるものです。

それ以外だと、実数の演算の解が虚数になってしまう演算についても許されない演算のひとつです。


割り当てられていない記憶領域へのアクセスは、今回発生してしまった問題の原因のひとつとして考えられます。

要するに、そのアプリケーションの動作で参照してはいけない部分を参照、または変更を加えるような状況です。


最初に「システムの設計で想定されていない動作」と書きましたが、実質的には「設計時に想定されるエラー」だと捉えられます。

一見矛盾しているようにも聞こえますが、そのシステムの動作として正しくない操作や挙動が発生することを想定して、想定外の動作を想定してあらかじめ例外として設定しておくことで実現されています。


Nullについては、イメージとしては「0」ですらない空っぽの状態、という例えをよく聞きますが、プログラムの世界では厳密にはこれは異なる場合が多いです。

Nullとはそもそも値が存在しない状態のことを指します。

メモリアドレスの格納を行うためのポインタがNullの場合は、どのアドレスも指し示さない特殊な状態(ヌルポインタ)と呼ばれたりします。


これが少し厄介なところで、アプリケーションを実行するマシンやシステムによってはNullの扱いが少々異なることがあります。

基本的にはNull=何も存在しない、何も指し示さない、という状態ではありますが、状況によってはシステムでも想定されていない、全く別のアドレスを指し示られている場合があります。

もしそういった状況でそのままポインタを参照してしまって、もしそれがシステムの全く別の数値を書き換えてしまったら…

アプリケーションによっては利用者の財産を扱っている場合もあります。


もしそういう部分を想定外の処理で書き換えてしまった場合、もはや目も当てられません。

Nullはプログラムを作るうえで非常に有用なものですが、同時に扱いに気を付けなければならないものです。


例外処理とNull、これらを並べて見た場合に今回のエラーがなぜ発生してしまったかが少し見えてくるかと思います。


つまり、参照先がNullなのでこのまま参照するのは想定外の動作を発生してしまいますよ、という状況であり、このままアプリケーションの続行を行っても解決しない問題であるために動作を停止してしまった、という状態であったというわけですね。

4. まとめ


今回はプログラミングにおける例外処理についてを深堀りして調査してみました。

例外処理もアプリケーションの開発においては非常に重要なものになりますので、今回の電卓アプリケーションとは少し離れてしまいましたが、しっかり調べてみました。


次回はボタンの参照設定から仕組みを考えてみたいとおもいます。

コントロールのプロパティを取得する方法を探ってみますが、今の技術レベルでは少し難しいような気もしていますので、もしかしたら各数字ボタンごとに処理を作るかもしれません。

今回はとにかく最低限の動作を行えるアプリケーションの開発を完了するところまでやり遂げ、細かいブラッシュアップに関しては後々考えながら着手したいと思います。