- - PR -
C# 戻り値の型を動的に変更することは可能ですか?
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-05-01 21:02
objectで返すのはイケてない、だから例外を投げるのがいい、と、勝手なユースケースを想定して話を進めているのがイケてないから、ref/outの話を書いたんですが。object型で値を返すことのデメリットは(ダブルミーニングという観点でも指摘されましたが)、不必要なboxingが生じてしまうことにもあります。イケてないといっても例外を投げるよりはずっとマシですが。 被害妄想がどーのこーのというのは意味不明なのですが(「被害」って何です?)、ダブルミーニングによる危険性の方が、常に例外を投げて呼び出し元で誰彼かまわずcatchしてしまう危険性より高いという決めつけが理解できません(そう主張しているんですよね。「定説」なんですから)。あなた(誰だか知りませんが)は何度もダブルミーニングや複数戻り値が危険である、何で分からないんだ、と書き続けていますが、誰もダブルミーニングが危険ではない、なんて言ってないのです(なるべく安全にしようとしているということは書きましたが)。 VBのERR云々も「かもしれませんが」と書いていることから理解出来て当然だと思いますが、あくまで推測ですし、拘るところでもないと思いますが。 | ||||||||||||
|
投稿日時: 2005-05-01 21:14
最初の例を、最初の質問通り、動的に戻り値の型を変更するとなると、このようなコードになります。
このメソッドの呼び出し側は、次のようになるでしょう。
最初に私が提示したものと比べてみてください。最初のコードが、かなりすっきりしていることがわかると思います。 **編集→「最初のコードが」を追加。 私が例外として実装することを薦めるのは、この呼び出し側のコードをすっきりさせる、つまり、使うときに迷わない、というところです。 今回、myFunctionは、int型かstring型しか返しませんが、それは本当でしょうか。誰がそれを保証するのでしょう? objectクラスは、.NET Frameworkでは、すべてのクラスの基本クラスです。どんなクラス宣言をしようが、暗黙的に親クラスとして指定されます(値型については知りません)。object型を返すということは、どんな型でも返せるということでもあります。もし、戻り値をint型としていれば、コンパイル時にcatchブロックのreturn文がエラーになるでしょう。しかし、object型を返すことになっているため、int型とstring型以外の型を返そうとしていても、そのミスは検出されません。 そのため、if文の判定で、intとstringに加え、elseを追加しています。 **以下追加 また、2回目の投稿で、『ほとんど必要ない検査を毎回実行するというのもパフォーマンスが悪いと思います』と書きました。このコードでは、戻り値がエラーが発生したかという検査を先に行っています。エラーが発生する状況は、正常な状況よりも少ないはずですから、エラーであるかという検査を先に行う分、パフォーマンスが下がります。もちろんこれは、検査の順番を入れ替えればすむことです。しかし、そこまで考えて呼び出し側をコーディングしなければならない、とも言えます。 **ここまで追加 このように呼び出し、というよりそのあとのコードが複雑になると、保守の手間を大幅に増加させます。2〜3ヶ月経てば、自分が書いたコードも他人コードです。何をやっていたのかわからなくなります。もちろん、ドキュメントが整理されていればそんなこともないのですが、理想と現実にギャップがあることは周知の事実です。 [ メッセージ編集済み 編集者: Jitta 編集日時 2005-05-01 21:47 ] | ||||||||||||
|
投稿日時: 2005-05-01 22:46
http://www.microsoft.com/japan/msdn/net/bda/exceptdotnet.asp
ここに下記のような記述があります。
よって、この演算結果がオーバーフローすることが、newborn氏の作っているプログラムで どのような意味をもつのかが不明確なので結論はでないのではないでしょうか。
これはさすがに言いすぎでしょう。 Jitta氏が戻り値をobjectにした例を書かれていますが、これをマシとは呼べないですよね | ||||||||||||
|
投稿日時: 2005-05-02 09:40
outパラメータを使う例
う〜ん、余計にしんどいです。 先のobjectで返す方法と違って、エラーかどうかの判定を必ず行わなくてはなりません。 例が単純だったので、例外が発生する状況がオーバーフローするということだけと思われたため、例外を発生させずに検査するようにしてみました。 実はこれ、バグがあります。負数の側の検査をしていません。しかし、コードからそれを読みとるのは困難ではないでしょうか。 また、エラーの時の戻り値を-1にしていますが、コメントに書いているとおり、業務ロジック上意味のない値にしておく必要があります(他所でのバグを回避するため)。業務上何らかの変更があって、意味のない値が変更になったとき、この値を変更しなければなりません。 | ||||||||||||
|
投稿日時: 2005-05-02 10:27
返り値をobjectにするなどというのはJittaさんの説明からも論外というのは分かるとして、
オーバーフローすることが仮定に含まれているというのなら、そのような作り自体が問題だと思います。 返すのは引数を1万倍したintの値です。 もしintの範囲を超えても良いなら、返り値をDecimalなどにすれば良いだけです。 そうしていないのですからintの範囲を超える場合はその値を使って作業を続行できない(しても意味がない)ということです。実際はもっと小さい値かもしれませんね。(-9,999〜9,999とか) ですので、まず"1万倍する"というメソッドに渡す前に値のチェックを終えておくのが「意図した機能を提供するための手段として例外を使用し(ない)」ための正しいつくりだと思います。 newbornさんのメソッドで例外を投げるのは何の問題もありません。 [ メッセージ編集済み 編集者: 一郎 編集日時 2005-05-02 10:30 ] | ||||||||||||
|
投稿日時: 2005-05-02 10:55
なるほど .NET の例外(Exception) は Java の例外(Exception) に対応するものではなく、Java のエラー(Error) に近い位置付けになるようですね。そのようなデザインルールになっているということであれば「投げっぱなし」「キャッチすべきではない」というのも納得せざるを得ないですね。.NET では Java でいうところの例外機構が扱えないということなので、不便そうな感じはしますが・・・。
私は、ref/out とやらの手法に対して、プログラマが気付きやすいとはいえ if文での判定を必要とする危険性は同じようにあります、と補足しただけなんですが。それに対して「誤解され」「信用されず」「全く使用されなくなってしまう」と風評被害にあったかのように言っているので、被害妄想かなあ〜と。誰も ref/out を否定していないのに、「誤解され」「信用されず」と感じること自体が被害妄想だよねえ。
いや、推測だからということではなく。ref/out も ERR もプログラマが if文を書くという点では同じでしょ。それなのに、自分ひとりで両案を持ち出して、ref/out は ERR よりずっと安全だ! とか言っているのが自作自演で滑稽だなあと思ったの。そんな自作自演してれば、そりゃ話もあさっての方向に行くだろうよ。だって、例外との比較がまったくなされていないんだもの。 とはいえ、結局のところ .NET のことを良く知らない私が(Javaを念頭において)例外の安全性を述べたことが場を乱してしまったようですね。すみませんでした。.NET ではユーザーコードで例外は「投げちゃいけない」「キャッチしちゃいけない」そもそも例外は使っちゃいけないものだったんですね。いろいろと勉強になりました。 | ||||||||||||
|
投稿日時: 2005-05-02 20:38
投げちゃいけない、キャッチしちゃいけない、というのは、極論かな?と。 例えば、ファイルを扱う場合、前もって検査することはできません。例外が投げられます。これはキャッチするべきでしょう。そうでないと、ユーザにとっては意味不明なメッセージが表示されますから。 「キャッチしろ」というのではなく、「キャッチしちゃいけない」は極論過ぎる、ということで。結局、ケースバイケースでしょう。 _________________ | ||||||||||||
|
投稿日時: 2005-05-03 04:46
未記入さんの意見への補足かな?
ここらへんの話、私なりに整理するとこんな感じですかね。
>> Jittaさん 未記入さんが言われているのは、「DotNETの例外はJavaの検査例外とは別物だから、Javaの検査例外と同じような感じで『投げちゃいけない』、『キャッチしちゃいけない』のですね」ってことなんだと思います。 ここらへん私も前々から気になっておりまして、DotNETのデザインガイドに厳密に従うと、エラー応答処理があちこちに分散するか、もしくはあちこちのメソッドでエラー情報を返すoutパラメータだらけになるかと思うのですが……、実際問題、どのような設計をされてますか? 私はデザインガイド違反を承知でJavaっぽくやっちゃってます^^; |