C++から移ってきたアナタへ。C#のref, outの使い方について。

with コメントはまだありません

C++からC#に移ってきて一番最初にモヤっとするのが、outとrefの使い分け。

関数の引数にrefを付けた場合とoutとでどう違うのか、レファレンスを読んで頭で理解できても、具体的にどういうケースで使い分ければいいのか(あるいは使わないのか)は判断しづらい。

それというのも、大抵のレファレンスは、refとoutを付けた場合の動作を列挙しているばかりで使い分けに言及していなかったり、値型と参照型に絡めて説明していないから。

そこで今回は、refとoutの使い分けをわかりやすく説明する(お)。

 

refとoutその前に

どういうケースでref / outを使い分けるべきか?は、その修飾子を付けるオブジェクトの種類によって二分できる。 なので使い分けを説明する前に、その種類について説明しよう。

 

1. 値型

C#には値型と参照型という2つの種類があり、値型のオブジェクトは数値(int)や構造体(struct)を指す。

この種類のオブジェクトを関数へ渡すとき、そのコピーが渡される

refとoutを理解する上で、ここが重要になる。

 

2. 参照型

一方の参照型は、クラスにあたるオブジェクトで、stringやList<T>など、C#のほとんどのオブジェクトがクラスタイプ。

参照型のオブジェクトを関数へ渡すと、その参照が渡され、コピーはされない

 

refとoutの使い分け

コーディング中、refとoutのどちらを使う、あるいは使わない(修飾子なし)かを迷ったとき、まずはそのオブジェクトが値型か参照型かを考え、次に、渡す先の関数でオブジェクトをどうしたいかを考える。

値型か参照型か?の2パターンに対して、別関数内でオブジェクトを使いたいだけかor書き換えたいかor初期化したいか?の3パターンを掛けて6パターン分の使い分けがある。

 

オブジェクトの種類 (呼び出し元のオブジェクトを)書き換える 初期化する 書き換えない
値型 ref out 修飾子なし
参照型 修飾子なし(refでも同じ) out ※参照型の場合は書き換えられてしまう。

 

C++erがC#をやって戸惑うのが、関数の引数にconstを付けられないということ。

だから、参照型のオブジェクトを関数に渡し、その先で書き換えられないようにすることはできない。各自書き換えないよう気をつけるべし!

 

呼び出し元のオブジェクトを書き換える場合、参照型は修飾子なしでもrefでも同じ動作になる(どちらも書き換えられる)けれど、ここは修飾子なしでいこう。refを付けてると、値型と参照型の違いを知らないと思われる、かも?

 

値型のそれぞれ

値型のオブジェクトの3パターンの作例がこちら。

 

参照型のそれぞれ

参照型オブジェクトだとこうなる。

 

 

C#おすすめ図書

他の言語をやったことがあって、その言語の作法でC#を書いちゃったことのある人へ

 

他人にとって読みやすいコードを書くための永遠の名著