2009/09/18(Fri) 17:54:07 編集(投稿者)
■No41366 (simano さん) に返信
> ですが、「参照渡しを行いたい需要もある」、
引数の型が値型であるか参照型であるかに関わらず、
引数に参照渡しを必要とする場合というのは通常、
No41329 のパターンにほぼ限られるかと思います。
それ以外のパターンだと、P/Invoke の場合ぐらいでしょうか。
> 例えば、サーバと通信して、「実データ」と「結果値」を受ける仕様になっているとします。
> 「結果値」が「クライアントから受けた値が不正です」だった場合の処理を書いてみました。
> (…略…)
> 上記の場合、(…略…)例外のパターンを把握するのも一苦労だと思います。
例外が嫌なら、「他の方法で通知する」か「失敗の理由は通知しない」のいずれかかと。
GetFromServer メソッドの利用側に、どのような記述を行わせるのであれば、
「一苦労しない」方法になると思いますか?
---------------
// 出力引数
ResultStatus status;
MyData result = obj.GetFromServer(0, out status);
if(status == ResultStatus.InvalidData) {
MessageBox.Show("失敗1");
return;
}
---------------
// 戻り値(値型)での判定
MyData resultStruct = obj.GetFromServer(0);
if(resultStruct.HasError) {
MessageBox.Show("失敗");
return;
}
---------------
// 戻り値(参照型)での判定
MyData resultClass = obj.GetFromServer(0);
if(resultClass == null ) {
MessageBox.Show("失敗");
return;
}
---------------
// エラープロパティでの判定
MyData result = obj.GetFromServer(0);
if(obj.LastDllError != Win32Error.NO_ERROR ) {
MessageBox.Show("失敗:" + obj.LastDllError);
return;
}
---------------
// エラー通知イベントでの捕捉
obj.OnError += delegate { MessageBox.Show("失敗"); }; // エラー理由はイベント引数で
MyData result = obj.GetFromServer(0);
---------------
// 例外処理
MyData result;
try {
result = obj.GetFromServer(0);
} catch(……) {
if(!Recovery(〜)) throw;
} catch(……) {
MessageBox.Show("失敗");
return;
}
---------------
# 他にも幾つかのパターンが考えられるかと思います。
> 「結果値」が「クライアントから受けた値が不正です」だった場合の処理を書いてみました。
結局、最後まで MyData が return される事が無いので、そもそもこのままだと
コンパイルエラーになってしまうかと思いますが、それはさておき。
> catch (Exception e)
> {
> throw;
> }
この catch 句は無意味だと思いますが……この場合の try/catch は、
どのような動作を目的として記述されているのでしょうか?
> MyData data = new MyData();
> data = Server_DataBytes_Value; // サーバの返した実データを渡す。
この記述からして、Server_DataBytes_Value とは、
MyData 型のフィールド変数のようですね。
この場合、最初に割り当てたインスタンスが意味をなしていません。
単純に「MyData data = Server_DataBytes_Value;」で良いかと。
> int val = Server_Return_Value; // サーバの返した結果値を渡す。
> if (val == ILLEGAL_ARG) // 「クライアントから受けた値が不正です」などのエラー値。
> {
> throw new MyServerException(val); // 自作の例外クラス
> }
上記の Server_Return_Value は、int 型のフィールド変数ですかね。
比較対象の ILLEGAL_ARG は…… int 型の定数でしょうか?
ここで、変数名を一旦 val に受け直している意図は分かりませんが
(変数名が分かりにくくなっただけのような…?)、何にせよ、
この『GetFromServer メソッド』というものは、
「サーバーと通信して MyData を返す。返せないときは例外を発生。」
という目的で実装されたメソッドという事になるかと思います。
で、その例外のひとつに、「new MyServerException(ILLEGAL_ARG)」がある、と。
> そこで、「結果値」は、戻り値として返す処理が適切なのかなと思いました。
例外だと把握しきれなくて、ILLEGAL_ARG などのint 型(を戻り値や出力引数)で
返す場合には把握することができる…という事にはならないかと。
> dllだったら例外のパターンを把握するのも一苦労だと思います。
それは例外に限らず、どのような返し方であっても一緒では無いでしょうか。
戻り値にしろ、出力引数にしろ、例外にしろ、それらに変更があったのであれば、
利用側にも修正が必要になるでしょうし、利用側に影響を与えたくないのであれば、
内部実装は変更しても、出力情報に対しては手を加えないようにするべきかと思います。
> 後でいつのまにか例外の種類が変わってたらcatchできません。
「例外の種類を変える」とは、どういう意味でしょうか?
・ILLEGAL_ARG の意味が変わったので、利用側が MyServerException.val を利用できなくなった。
・MyServerException の例外が、サーバーエラー以外に対しても throw されるようになった。
・MyServerException を廃止して、別の例外が throw されるように実装し直した。
・MyServerException だけでなく、他の新たな例外も throw される可能性が出てきた。
・素の MyServerException でなく、その継承クラスを throw させることになった。