83277


関数に値を渡して、その値を使って計算して別の値が返ってくるような関数は多いと思いますが、その際に`return`か`ref`でどちらでも実装できるともいますが、どちらのほうが良いでしょうか？

以下の例ではiがintですが、iがでかいクラスなどだと変わるでしょうか？

[code]

    public static void Main(){
        int i = 5;
        i = value1(i); //値渡し
        System.Console.WriteLine(i);
            
        i = 5;
        value2(ref i); //参照渡し
        System.Console.WriteLine(i);
    }
    
    // 値型の値渡し
    public static int value1(int x) {
        x *= 10;
        return x;
    }
        
    // 値型の参照渡し
    public static void value2(ref int x) {
        x *= 10;
    }
    
[/code]


CC BY-SA 4.0
2021-10-26T06:36:28.670
83269
2021-10-26T15:48:33.833
2021-10-26T15:48:33.833
3060
40856
question
c#
C#においてreturnとrefどちらを使うべきか


通常はreturnを使った方がいいと思います。  
この方が、関数の結果を知りたいことが、はっきりします。  
refではその引数を関数の中で参照したいのか、それとも値を返したいのかわかりにくくなります。  
また、関数の中で参照の必要が無くrefと同じように引数として渡す場合はrefよりoutのほうがいいと思います。


CC BY-SA 4.0
2021-10-26T07:49:58.243
83270
2021-10-26T07:49:58.243
24490
83269
answer


理由はいろいろ思い浮かびますが、単純に戻り値には`return`を使うべきです。

  * `ref`を使うと呼び出し側は引数と戻り値を同一の変数で扱うことを強要されます。`return`であれば、呼び出し側は引数と戻り値を別の変数で扱う自由度が生まれます。
  * `ref`の場合、呼び出し側はプロパティを渡すことができなくなります。プロパティは内部的には`get`メソッドと`set`メソッドの組み合わせだからです。`return`であればそのような制約はありません。
  * `ref`を使うと内部的には変数のアドレスを固定する必要が生じます。具体的にはメソッド実行中にGCに当該変数を移動されると結果が不正になるため、それを抑止する必要があります（完全にインライン展開されればそのような処理も不要とJITが判断できるかもしれませんが）。`return`であればそのようなオーバーヘッドは不要です。

* * *

一応、古いガイドラインがあり[パラメーターのデザイン](https://docs.microsoft.com/ja-
jp/dotnet/standard/design-guidelines/parameter-design#parameter-passing)には

> ❌ `out` または `ref` パラメーターは使用しないようにしてください。
>
> `out` または `ref`
> パラメーターを使用するには、ポインターの使用経験、値型と参照型の違いの理解、および複数の戻り値を持つメソッドの処理が必要になります。 また、`out`
> パラメーターと `ref` パラメーターの違いはあまり理解されていません。 一般的な開発者を対象にフレームワークを設計する場合、ユーザーが `out`
> または `ref` パラメーターの処理を習得していることは期待しないでください。

と定められています。


CC BY-SA 4.0
2021-10-26T13:06:41.890
83277
2021-10-26T13:06:41.890
4236
83269
answer