既存システムで、戻り値をvoiにして、refを使って、値を代入してるコードを見ました。
かなりの処理にわたりrefで値を変えている。。
アドレスを参照してるので、早いとは思うのですが、入力値としての引数と、値が変わる引数が混在してるのは、個人的に好きではないのですが、、、
C言語っぽい感じがするんです。。。
しかも、voidですから、最低でもどのうような状態でおわったのか、戻り値で知らせるべき。。
もしくは、例外を投げるべき。。。
大規模になると、コードを追っていくのがわかりずらくなると思うんですが。。
戻り値を返し、メッセージパッシングをすべきだと思うのですが、、、
どのように使い分けているのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
私の偏見ですが、そのコードを書いた人は元VB6(≠VB.NET)プログラマーだったのでは無いでしょうか?VB6時代の文法なんて、今時はExcel等のマクロに使うVBA(厳密には同じでは無い)ぐらいでしかお目にかかる事はありませんが、次のような特徴を持ってました。
- 戻り値を返さない本当のサブルーチン(Sub)と戻り値を返す関数(Function)が別にある。(これだけはVB.NETも同じ)
- 関数(Funciton)の戻り値の返し方が、Return文ではなく、
関数名 = 値
というものだった。しかもそこで処理が終わるわけでは無い。(なぜ、こんな書き方にしたのか私には理解できない。) - 引数のデフォルト(指定しない場合)がByRef(参照渡し)だった。(逆に、VB.NETからは省略すると勝手にByVal(値渡し)が付くようになったそうです)
Subの方が短い。関数名に代入が可読性を落とす(ような気がする)。デフォルトは参照渡しだから、そのまま書き換えた方が便利。等と思って、VB6時代に関数(function)ではなくSubを用いた手続き(procedure)を書くことがその人の主流になってしまったと思われます。
このような書き方はVB6時代の負の遺産だと私は思っています。C#では次の理由で(巨大な構造体を使っているなど特定の条件下を除いて)ref
を使うことは避けるべきです。
ref
で参照渡し(call by reference)にすることで速度面の恩恵を受けられるのは、値型である構造体のみです。(通常の参照型の値渡しは参照の値渡し(別名:共有渡しcall by sharing)になるため、値渡しだと遅くなるわけではありません。また、intなどの値型の単純型は、参照を同じするという処理が無い分、値渡しの方が速いと考えられます)- 複数の戻り値を返したい場合は、出力であることが明示できる
out
を使うべきです。(入力と出力を兼任させる事は、コードを複雑にするため、避けるべきです。また、C#7以降はタプルを返せるようになるようですので、タプルを使うべきです。)
参照渡しができる言語は少ないほうであり、メジャーな言語としては、F#、VB.NET、C++、PHP、Perl(でも、Perl6にはなさそう?)ぐらいしかありません。Cはポインタの値渡しはできますが、参照渡しはできません。Javaは値渡ししかありません(オブジェクトは参照値を値渡ししているだけです)。PythonとRubyは全て参照の値渡しです。
- C++のclass/structはC#でいう値型の構造体であるため、参照渡しは速度面で有利です。とくに、巨大なclass/structをC++で参照渡しをすることは大変意味があります。ただ、戻り値の一つとして扱わない場合は、constをつけて変更不可にすべきでしょう。
- F#は.NETで他にあわせるために参照渡しがあるだけのようです。複数の戻り値を返す場合はタプルを使うべきでしょう。
- PHPはarrayが値渡しであるという時点で、察してください。
- PythonやRubyでは、すべてのオブジェクトがC#でいう参照型であり、速度面で参照渡しにする意味がありません。また、配列やタプルで複数の戻り値を返すことができるため、複数の戻り値のための参照渡しも意味がありません。ですので、参照渡しは初めから存在しません。
このように、参照渡しがある言語では速度や複数戻り値などの必要に迫られて実装しており、その必要がない言語では初めから実装しないようにしてあります。つまり、参照渡しは必要にならない限り、使うべきではないというのが私の中の結論です。不必要にref
を使っている、そんなVB6っぽいコードはさっさと捨てる事をお勧めします。
投稿2016/07/11 18:55
総合スコア21737
0
こういうのは意見が多い方がいいので特別な意見は無いのですが。。。
多分、書いた人の癖ですね。Cでは、戻り値をintにしてエラーコードを返す人がいるので、その手の話だと思います。
その言語で一般的に書かれている書き方をどのていど踏襲するかはそれぞれ意見があると思いますが、まあ、取り敢えず三人が”良くはない”とわざわざ書き込んだという程度には良くはないといえます。
また、returnで値戻せないので、ソースコードを読みづらくしている可能性が高いです。
アドレスを参照してるので、早いとは思うのですが、
(画像処理や機械学習など計算量がよほど多くないと)恐らく変わりません。渡しているのがオブジェクトであれば、refと同様ポインタが渡されます。基本型であれば、何バイトか増える程度なので、ファイルIOやDBアクセスやネットワーク通信がある通常のプログラムでははっきりした差にはならないはずです。
追記
しかも、voidですから、最低でもどのうような状態でおわったのか、戻り値で知らせるべき。。
見落としていました。本題とは直接の関係ないですが・・・
状態を伝える場合は、例外を使うのがC#の一般的な流儀です。
(致命的なエラーでなくても、例外は使います。)
投稿2016/07/11 16:02
編集2016/07/11 16:27総合スコア2883
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
便利な時もありますが、
基本的には可読性が悪いので、止めれるなら止めるべきだと思いますね。
使い分けというより、「使わない」って感じでしょうか。
もしくは使わない努力をする。
かなりの処理にわたりrefで値を変えている。。
この一言で何となくソースコードのイメージがつきます。
最悪だと思いますね。
参照から値を変更ってのは、関数型言語の思想とも反しますし、
もし今後、関数型言語をする時がきたら、
日常的に参照渡しを行っていたオブジェクト指向プログラマーはつらいかもしれないので、
やはり止めれるなら止めといた方がいいと思います。
ref変数を使うのでなくリターンすべきだと思います。
投稿2016/07/11 14:40
総合スコア4666
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。