C# 7の説明、1つ足しました。参照戻り値がらみ。
参照戻り値と参照ローカル変数
追加される構文自体は割とシンプルなんですが、活用できそうな場面まで含めて説明しようとするとなかなか骨が折れる感じの機能。
- 機能自体の説明: 参照戻り値と参照ローカル変数
- 前提知識として、値型を使わないとパフォーマンス出しにくい場面があるという話: 値型の性能
- で、値型を使ってパフォーマンスを出そうと思うと参照渡しが避けられなかったりするという話: 値型の参照渡し
まず、メモリ管理の方法について(スタックとかヒープとか)知ってないとピンとこないですしね。
「別の何かを参照する」って考え方も、そこそこ素養を求める概念ですし。 C言語とかC++で「ポインターは難しい」とか言われるのも、同種の問題だと思います。
ということで、GitHub上のディスカッションでも、大体は、
- 活用場面がよくわからない
- (自分は)使わなさそうなのに、複雑性を増すのには反対
- 構造体は immutable に作れってのが常識じゃないのか
なんて話がまずあって、それに対して、
- メモリ管理の手法とか知らない人はそう言って、パフォーマンスをいとも簡単に落とすんだ
- パフォーマンスを求めると、mutable な構造体を配列で持っとくしかない場面があるんだ
とかの返事が毎度ついてる感じ。
文法自体についての反対意見はあんまりなさそう。しいて言うなら、
- 非同期メソッドとかイテレーターとかでも使いたいけど、
Task<ref T>
とかIEnumerable<ref T>
は作れないよね? - ローカル変数の宣言で、
var
(変数の型推論)を使う場合ですらref var
って書かないといけないのはちょっと面倒
みたいな話が出てるくらい。
まあ、なかなか活用しどころが想像しにくい機能ではあるんですが、C# チーム的には優先度結構高いでしょうね。 Build Insiderの方で書きましたけど、 今、パフォーマンスに対する要求がかなり上がってるので。 .NET Core関連のチームとか、C#チーム自身とかにとってはかなり有用な機能のはず。 多くのプログラマーにとって直接使うことがない機能であっても、 低レイヤーなライブラリとかツールとかの性能向上が見込めるので、間接的な恩恵はそこそこありそうな気がします。
6/6 追記:
この手のメモリ管理がらみのパフォーマンス改善の話に付いて回るのは、ガベージコレクションもかなり高性能になってて、もうガベコレに任せてても大体大丈夫なんじゃないかという議題。
確かに、MS製ガベコレって結構高性能なんですよね。それでもガベコレ除けをきっちりするとかなりのパフォーマンス改善したりしますが。 仮にまあ、ガベコレがもっともっと優秀になったとしても…
その優秀なガベコレがどこででも使えると思うなよ!
と思うわけです。 ガベコレのコードなんて、.NETのものなんてファイルサイズが1.2MB(GitHubに"we can't show files"って言われるやつ)、行数3700行を超える長大なC++コードです。どこまで手書きでどこまで機械生成かわからないなんて話もありますが、どちらにしたって、なかなか保守が大変そうな分量。 特定の1環境で保守するのはまだ成り立つんですが、全然スペックの違う異なる環境向けにそれぞれ提供とかにあると、なかなか大変そう。 要するに何が言いたいかというと、あんまりこういうレイヤーの改善に期待してると、新しいプラットフォームに移りづらくなるとかのリスクもあったり。
具体的に、最近自分はUnityでiOS/Android両対応のゲームを作ってるわけですけども、 どうも、ヒープ確保の性能がiOSとAndroidでだいぶ違うみたいで、同じコードを書いててもAndroidでだけパフォーマンスが出なかったりします。 (他にもパフォーマンス ネックの原因になってそうな場所は多いんですが、ヒープ確保もネックの1つなことは間違いなさそう。)
一般論としても、「ムーアの法則での発展を期待していたら、モバイルな時代が来ちゃってむしろ時代が巻き戻った」なんて言葉よく聞くわけでして。 今更ながらC#に参照戻り値みたいな「使う人を選ぶ」機能が入るのも、そういう時代背景があるんじゃないかなと思います。