- PR -

C# 戻り値の型を動的に変更することは可能ですか?

投稿者投稿内容
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-04 23:15
南部です。
引用:

未記入さんの書き込み (2005-05-03 14:52) より:
(略)
与えられたユーザー名とパスワードが正しければ true を返します。与えられたユーザー名とパスワードが正しくなければ false を返します。正しいかどうか分からない場合は例外を投げます。正しいかどうか分からないというのは、たとえば、認証に使用しているユーザーエントリファイルやデータベースが破損か何かで読み取れないような状況です。この場合、正規ユーザーもログインできませんので、true を返すのも false を返すのもふさわしくないわけです。それと、login メソッド内全体を try-catch で囲んで LoginException(RuntimeExceptionの自作サブクラス)でラップしているのは login というメソッドの性質上デリケートそうだったからです。素の FileNotFoundException や SQLException がそのまま上位に伝播するのを見逃すと、ログイン機構の仕組みを外部に露呈することになる可能性があるからです。


はい、未記入さんの設計のように、メソッドの役割、性質、責任範囲等
きちんと考慮されていると.NETもJavaも実装はそんなに変わらないこと
が分かります。

引用:

k-nakさんの書き込み (2005-05-03 16:34) より:
(略)
仕様変更:
ログインに失敗したときは「IDまたはパスワードが違います」、「業務時間外です」などの失敗理由も通知するようにして欲しい。
(略)


この場合、業務エラールートを表現できる戻り値を作るのはどうでしょう?
enum LoginStatus
{
 認証OK,
IDまたはパスワードが違います,
業務時間外です
}

引用:

Jittaさんの書き込み (2005-05-04 07:05) より:
それじゃぁ、.NET Frameworkのデザインルールに従うと、こんな感じ?
(略)


いえ、一番最初のコードです。
最初のコードで、きちんと「例外」をキャッチしています。
本来、このメソッドに例外をハンドリングする役割があれば、
(つまり業務エラーなのかアプリケーションエラーなのかを判断できる。
 さらに言えば、業務エラーがきちんと想定・設計されている)
ハンドリングして、戻り値を返します。
が、所詮、例としてのコードなので業務フローなどなく、
ライブラリとして、「例外」を投げていいかと。
#業務エラーかどうかなんて判断できないし。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-05-05 09:04
引用:

nanbuさんの書き込み (2005-05-04 23:15) より:

最初のコードで、きちんと「例外」をキャッチしています。
本来、このメソッドに例外をハンドリングする役割があれば、
(つまり業務エラーなのかアプリケーションエラーなのかを判断できる。
 さらに言えば、業務エラーがきちんと想定・設計されている)
ハンドリングして、戻り値を返します。


 では、「入力値は0以上100未満の整数」という指定があれば、「範囲内に収まっているか」という検査を行うメソッドを用意する。そうすると、myFunctionが(この例の範囲では)例外を返すこともない、と?
 今の私の設計では、検査を行うのはmyFunctionの中で、ArgumentOutOfRangeExceptionを投げています。
_________________
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-05-05 14:08
unibon です。こんにちわ。

(Java ですが、
「NumberFormatException が非チェック例外なのはなぜ?」
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=7503&forum=12
に少し近いかなと思いました。)

私は昔は VB と Java をやっていましたが、VB だと結局は Java での非チェック例外に相当する実行時例外にビクビクしながら On Error を書きまくる毎日でした。Java だと、非チェック例外とチェック例外があって、どっちにすべきか悩むものの、基本的にはチェック例外だけを catch すれば良く、catch 漏れはコンパイルエラーになるので、安心できました(多少コードは try/catch でゴミゴミはしますが)。
最近、Java から .NET に心変わりしたのですが、当初は、.NET だと非チェック例外しかないのは、きっとなにか割り切りがあって、チェック例外が要らないすばらしいバラ色の世界なんだろうと期待していました。が、実際にコードを書いて見ると、そうではなく要は VB の悪しき世界の再現なのではないかと不安に思う毎日です。C# や VB.NET を使えば On Error よりは強力な構文で割りと楽に catch はでき、コードの書きやすさはたしかにありますが、でも、いつ例外が起こるか分かりにくい、という点では VB との違いはないと思います。
そういう考えから言えば、.NET において、アプリケーションの単なるロジックには例外は使うのはできるだけ避けたほうが良いと思います。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2005-05-05 16:02
引用:

Jittaさんの書き込み (2005-05-05 09:04) より:

 では、「入力値は0以上100未満の整数」という指定があれば、「範囲内に収まっているか」という検査を行うメソッドを用意する。そうすると、myFunctionが(この例の範囲では)例外を返すこともない、と?


この設計だと
「myFunctionが例外を返すこともない」ではなく、
「myFunctionから「例外」がスローされることは想定されていない」
ですね。
つまり、myFunctionが例外をスローした場合、
「このビジネスフロー」では業務エラーではなく、
まさに「例外」です。

引用:

Jittaさんの書き込み (2005-05-05 09:04) より:

 今の私の設計では、検査を行うのはmyFunctionの中で、ArgumentOutOfRangeExceptionを投げています。


この場合、myFunctionからArgumentOutOfRangeExceptionがスローされることは、
想定・設計されています。
しかし、myFunction内では業務エラーなのか、アプリケーション/システムエラーなのか
判断することはできない、ということでもあります。
なので、myFunctionを使用している部分で、必要であれば、
この「例外」を業務エラーに切り替える必要があります。
nak2k
ベテラン
会議室デビュー日: 2003/07/17
投稿数: 86
投稿日時: 2005-05-05 22:17
余談ですが、DotNETフレームワークにはドキュメントに載ってる例外がスローされない場合や、逆にドキュメントに載ってない例外がスローされる場合がありますのでJavaから入られた方は特にご注意を。(XmlSerializerクラスに、getterあるいはsetterのみのプロパティのあるクラスを渡したときの例外とか、原因究明に時間かかった覚えが……)
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-05-06 07:36
引用:

最近、Java から .NET に心変わりしたのですが、当初は、.NET だと非チェック例外しかないのは、きっとなにか割り切りがあって、チェック例外が要らないすばらしいバラ色の世界なんだろうと期待していました。



割りきりがあるとは思いますが、バラ色の方向ではないですね。

.NET ではアセンブリの動的ロードやリフレクションが積極的に利用されていて、チェック例外をチェックのしようが無い状況が日常的に発生する(=コンパイル時にどんなチェック例外が発生するかどうか分からない)ため、Java のようなチェック例外が定義されてないんでしょう。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
newborn
常連さん
会議室デビュー日: 2005/04/28
投稿数: 34
お住まい・勤務地: JAPAN
投稿日時: 2005-05-06 13:41
スレッドをたてたnewbornです。
ゴールデンウィークの間、パソコンを開かなかったので、まずレスの多さにびっくりしました。
回答してくださった皆様、本当にありがとうございます。
スレッドを立てた時のコードはあくまでも質問のためにサンプル的に書いたものでして、実際にわたしが行いたい処理内容とは異なります。
この点を皆様が推測しながら回答していただいて本当に恐縮です。

質問させていただいた経緯を申しますと、
C#.NETとFlashでウェブアプリを制作していて、.NETのエラーをクライアントであるFlashに返して、エラーの発生を通知したくて今回このスレッドを立てさせてもらいました。
下記のコードサンプルでは、ファンクションの戻り値はDataTableですが、
エラーが発生した場合、下記のコードでDebug.WriteLineの部分をFlashに返したいわけです。その際、戻り値の型はstringである必要があるので矛盾が生じてしまうのでは
と思ったわけです。



public DataTable myFunction(string sql){

dbaccess db=new dbaccess();
OleDbConnection sConn=db.connect();
sConn.Open();

DataTable table = new DataTable();
OleDbDataAdapter sAdapter = new OleDbDataAdapter(sql , sConn);

try{
sAdapter.Fill(table);
}catch(OleDbException e){
Debug.WriteLine(e.ToString());
}catch(Exception e)
Debug.WriteLine(e.ToString());
}finally{
sConn.Close();
}
return table;

}


よろしくお願いします。

newborn
常連さん
会議室デビュー日: 2005/04/28
投稿数: 34
お住まい・勤務地: JAPAN
投稿日時: 2005-05-06 15:05
皆さま、お世話になっておりますnewbornです。
自己レスですが、flashにエラーを返すことができました。

catch(OleDbException e){
throw new Exception("DBエラーが発生しました。",null);
}

でちゃんとflash側にエラー内容を返すことができました。
私は、例外を投げるということが、やっとでちょっと理解できたような気がします。

皆さま、本当にお騒がせいたしました。m(-_-)m

スキルアップ/キャリアアップ(JOB@IT)