7から、戻り値とローカル変数でも参照渡しを使えるようになりました。書き方はほぼ参照引数と同じです。戻り値の型の前、値を渡す側、値を受ける側それぞれにref修飾子を付けます。例として、配列のi番目の要素を参照で返してみましょう。以下のようになります。4また、ローカル変数に対しても、ref修飾子を付けることで参照渡しができます。これは普通に値渡し(コピー)。0refだらけになってしまいますが、渡す側、受け取る側の両側にref修飾子が必要なのは参照引数と同様です。元の変数がどこか遠くの知らない場所で書き換えられるかもしれないというのはそれなりに危険なことなので、あえて面倒な構文になっています。上記の例でも、参照引数を参照戻り値で返して、それをさらに参照ローカル変数で受け取るものもあります。ここだけ抜き出すと以下のような感じです。x;これで、下図のような状態になっています。これくらい単純な例でも、結局どこが書き換わるのかそこそこわかりづらくなるので注意が必要です。「どこを参照するか自体を書き換え」という操作が考えられます。この機能は使えません)。参照戻り値で返せるものもし何の制限も掛かっていないなら、参照渡しでは参照をたどった先の大元が消えしまっている可能性があって危険です。C#の参照渡しでは、そうならないように、参照できるものを制限しています。(他のプログラミング言語では、参照渡しが必ずしも安全でなかったり(不正なメモリ操作につながる)、逆に参照渡しの機能を提供していないものもあります。.NETも、ILのレベルでは安全でない参照もできたりします。C#は、コンパイラーが厳しめにチェックして、安全でない参照ができないようにしています。7では、コンパイラーが賢くなって、この「大元をたどって調べる」という仕事ができるようになったので、参照戻り値や参照ローカル変数が使えるようになったということです。7でも、あくまでメソッド内で完結できる範囲でしか「たどって調べる」ということができません。以下のようなコードはコンパイルできません。コンパイラーはそこまでは追ってくれません。(こういうXの中身次第で変わる挙動を認めてしまうと、Xの変更の影響がX利用側(この例の場合Y)に及び過ぎるため問題があります。「追ってくれない」というより、意図的に「追わない」という面もあります。1つ注意が必要な点があります。構造体の場合、フィールドの参照を返せません。ref引数拡張メソッドをを救済策として使えます。クラスの場合はOK}ちなみに、エラーになるのは構造体のフィールドの参照を直接返している場合だけです。以下のように、フィールドを介していても、参照型の中の参照を返すことはできます。_offset];}構造体内では、フィールドの読み書きのために、実はthisが参照扱いになっています。結局「構造体はフィールドの参照(thisが絡む参照)を返せない」という制限を掛けたそうです。この仕様は、少し詳しい人であれば何か釈然としないものがあるかもしれません。以下のように、拡張メソッド的に(静的メソッドで)書けば似たようなことが実現できます。このコードが許されるのに通常のメソッドでは許されないというのは少し不思議です。正確には、「以下の2つのうちどちらか片方を選ぶ必要があり、前者を選んだ」ということだそうです。7で選んだ仕様)構造体の関数メンバーを呼ぶ際には、常にthis参照が引数として渡っている前提で安全性を調べる(選ばなかった仕様)要するに、以下の例の、Okメソッドのようなものを認めるためには前者の仕様が必要です。}}あと、以下のように、ジェネリクス絡みの問題を避けるためにもこの仕様を選ぶ必要があったそうです。7.2から、条件演算子の2項目、3項目を参照にできるようになりました。以下のような書き方ができます。ref」は、左辺にも使えます。どちらかを書き換える」みたいなことができます。限った話ではなく、単に演算子の優先度の問題です。代入と条件演算子が並んでいる場合、右から順に結合するので、()がなければ代入が先に解釈されます。参照戻り値と参照ローカル変数でも「参照渡しだけども読み取り専用」という渡し方ができるようになりました。readonlyで修飾します。y)の方はrefだけ書きます。readonlyと書かせる案もありましたが、out引数との対称性がきれいだったため、最終的にはinの方が採用されました。reassignment)というものができるようになりました。参照先の値の書き換えではなく、「どこを参照しているか」自体を書き換える機能です。以下のように、参照ローカル変数への代入時に、右辺にrefを付けることでref再代入になります。