Build Insiderオピニオン:岩永信之(17)
C# 7.1: 半年でのマイナーリリース
C# 7で始まったリリースサイクルの短期化に伴って、つい先日C# 7.1がリリースされた。そこに含まれる新機能、C# 7.2/7.3に含まれる予定の機能、そこから見えてくるものについて考えてみよう。
今回は、連載第8回で話した「短期リリースサイクル化」の続報、あるいは、経過報告的な話となる。
Visual Studio Update 3のリリースに伴い、C#もC# 7.1がリリースされた。
C# 6.0~7.0の間は1年半程度で、それ以前の2年半~3年程度のリリースサイクルと比べるとだいぶ短くなっている。これに対して、次のC#はC# 7.1、すなわち0.1単位のマイナーリリースとなり、7.0から半年足らずというかなりの短期リリースサイクルになっている。
新機能の小出し
第8回での説明の通り、リリースサイクルの短縮に伴って、追加される新機能も小出しとなっている。例えばコード1に示すのはC# 7系のいつか(8.0よりは前。7.Xと仮称)までには書けるようになる予定のコードだが、C# 7.0の時点では2つもしくは3つのコンパイルエラーが発生する。
int x = 1, y = 2;
var t = (x, y); // エラー1(CS8179)、ValueTupleの参照
var s = t.x + t.y; // エラー2(CS1061)、要素名の推論(C# 7.1)
if (t is (int, int)) { } // エラー3(CS0150)、タプル型でのis(C# 7.X)
|
エラー1は、C# 7.0の時点でも回避できるエラーである。エラーになる理由は、(C#言語機能としての)タプルがValueTuple
構造体(System
名前空間)に依存していて、これがまだ標準ライブラリに含まれていないことだ。標準ライブラリに追加されるのは以下のバージョンからで、いずれもC# 7.0(2017年3月リリース)よりも後である。
- .NET Framework 4.7: Windows 10 Creators Update(2017年4月提供開始)に同梱。一般提供開始は2017年5月から
- .NET Standard 2.0、.NET Core 2.0: 2017年8月提供開始
これ以前のバージョンでは別途System.ValueTuple
パッケージの参照が必要になる。
エラー2は、C# 7.0の時点ではタプルの要素名の推論が働かないためである。タプルを宣言する側を(x: x, y: y)
と書くか、使う側をt.Item1, t.Item2
と書く必要がある。推論しすぎによるミスを生む可能性を警戒して、7.0時点では実装を見送ったが、その後、7.1での採用が決定した。
エラー3は、通常の型であれば「変数 is 型名
」という式を書けるが、それを現時点ではタプルに対して認めていないために発生する。C# 7.Xで入る予定の完全版パターンマッチングと書き方が被るため、半端な状態で実装して将来的に困ることを懸念してのことである。逆にいうと、7.Xでは認められる予定だ。
これだけの短いコードからでも、以下のようなことが分かる。
- .NETの更新タイミングを待たない
- 標準ライブラリへのValueTuple
構造体の追加を待っていたら、タプルのリリースが約半年遅れることになる
- パッケージ参照で解決できる
- 新機能を小出しにする
- 1つのタプルという機能であっても、要素名の型推論だけ後というようなことがある
- 一見単純そうな機能でも、懸念点をつぶすのに時間がかかることがある
- 小出しであっても、将来の変更はちゃんと考慮に入れている
- 将来予定されている機能との被りを理由に、現時点では認めていない機能がある
7系マイナーリリース
C# 7.1は、C#にとって実質的* に初めてとなるマイナーリリースである。この7.1を皮切りに「7系のマイナーリリース」が続くことになるが、マイナーリリースで入る機能はおおむね以下のいずれかのパターンに当てはまる。
- (1)「パレートの法則」(2割の実装が8割のユースケースを満たす)的な優先度付けによって、先に2割に当たる部分だけが7.0で提供されたもの
- (2)良いアイデアだが、出た時期がぎりぎり過ぎて、7.0には入れられなかったもの
- (3)実装は簡単だが、細かい仕様に関する合意形成が難しかったもの
以下、具体的な機能を挙げていくが、上記のいずれのパターンに当てはまるかに応じて、(1)(2)(3)と注記も入れていく。
- *1 一応、C# 1.1というバージョンがあるが、XMLドキュメントコメントやプリプロセス命令に関する機能追加のみで、多くの人にとってはほとんど影響のないリリースだった。現在の感覚で言うとパッチリリース扱いで1.0.1とされていてもおかしくはない。
C# 7.1
リリース間隔が短かったこともあり、C# 7.1で入る新機能は以下のように非常に小さな機能が4つだけである(いずれもGitHubのcsharplangリポジトリ上の提案issueページにリンク)。
- “default” expression(2)
- tuple projection initializers(1)
- “pattern-matching” with generics(1)
- Async Main(3: 案としてはC# 6.0のころからあったが、GUIアプリのように同期コンテキストを持つべきかどうかで悩んだ)
4つまとめて説明しても、100行未満のデモコードで収まる程度のものである。
「7.1マイルストーン」の変化
ちなみに、初期の段階の計画としては、「7.1マイルストーン」にはもっと多くの機能が含まれていた。例えば以下のようなものがある。
7.2マイルストーンに変更:
- Auto-Implemented Property Field-Targeted Attributes(2)
- Private protected(3: このキーワードでいいかどうかが難しい。連載第1回を参照)
7.Xマイルストーンに変更:
- Nullable-enhanced common type(2)
- Expression variables in initializers(1)
- Mix Declarations and Variables in Deconstruction(1)
- Pattern Matching(1)
要するに、初期段階では7.1のリリース時期が決まっていなかったため、7.0の積み残しのうち優先度が高いものや簡単そうなものを取りあえず7.1マイルストーンに並べていた。その後、リリース時期が決まったことで、そのタイミングに間に合うものを取捨選択した結果が現在のC# 7.1である。
ちなみに、C# 7.1に入った機能には、テストなどが間に合っていないだけでC# 7.0のリリース前からすでに実装があった(から今のリリースに間に合った)ものが多い。「7.2行き」と「7.X行き」の差も似たような感じで、現状「7.2行き」となったものはすでに大まかな実装が終わっている。
補足: C# 7.2
前節の話を見て、「完全版のパターンマッチングが7.2を飛ばして7.Xになった」という点を残念、あるいは不思議に思う人もいるだろう。実は、おおむね「間に合うものを取捨選択」で決まったと思われるC# 7.1とは異なり、C# 7.2ではテーマが決まっている。その結果、テーマ外のものはほぼできている数点を除いて「7.X行き」となっている
では、C# 7.2のテーマは何かというと、それは「パフォーマンス」である。連載第6回、第7回で書いた通り、今、C#や.NETにとってパフォーマンスは非常に大きなテーマになっている。C# 7.0の時点でも参照戻り値という機能がすでに入っているが、この延長線上にある機能が7.2マイルストーンに多く含まれている。
このパフォーマンス関連の話については、次回以降に取り上げていく予定である。
Visual Studio Update
前述のタプルの話などから察せるように、C#のリリース時期はWindowsや.NET Frameworkとはそろわなくなった。しかし、今のところ、Visual Studioとはある程度足並みをそろえるようである。Visual Studioのリリースは現在、図1に示すようになっている。
15.0などの数字はVisual Studio 2017の内部バージョンである。リリースノートなどでよく見る数字だろう。メジャーバージョンの15がVisual Studioの「2017」に相当し、マイナーバージョンの「.1」「.2」「.3」がそれぞれ「Update 1」「Update 2」「Update 3」に対応する。
C# 7.0はVisual Studio 2017(15.0)と同時にリリースされているし、C# 7.1はVisual Studio 2017 Update 3(15.3)とともにプレビュー版がリリースされてきた。
一方で、15.1と15.2ではC#の更新はなかった。15.1はWindows 10 Creators Updateに合わせたものでUWP関連の機能の追加、15.2はMicrosoft Build 2017での発表に合わせてデータサイエンス関連の機能追加があった。それなりにまとまった単位の機能追加があったためマイナーバージョンを改めたものだろう。
Visual Studioの今後のマイナーリリースでも、C#の更新はかからない短めのリリースと、更新がかかる長めのリリースの両方があるかもしれない。いずれにせよ、C#のリリースは以下のような流れになっていくと思われる。
- 半年に1度程度、マイナーリリースがある
- マイナーリリースも、正式リリースに先立ってかなり早い段階からプレビュー版が提供される
まとめ
第8回では「C#も年に1度程度のリリースを目指したいようだ」という話もしたが、その後、どうやら半年でのマイナーリリースができる体制が整ったようだ。また、マイナーリリースでも、正式リリースに先立って早い段階からプレビュー版を試してみることができる。
その分、機能追加は小出しになっているが、ちゃんと将来的な拡張を阻害しないよう考慮しつつ実装を進めているので安心してほしい。C# 7.1は特に「間に合うものを選んで残した」という印象だが、これも短期リリースサイクルを前提としたブランチ管理に馴れてきた結果だろう。
岩永 信之(いわなが のぶゆき)
※以下では、本稿の前後を合わせて5回分(第13回~第17回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
13. インターフェースを「契約」として見たときの問題点 ― C#への「インターフェースのデフォルト実装」の導入(前編)
C#におけるインターフェースとは、ある型が持つべきメソッドを示す「契約」であり、実装は持てない。だが、このことが大きな問題となりつつある。今回から全3回に分けて、C#がこの問題にどう対処しようとしているかを見ていく。
14. デフォルト実装の導入がもたらす影響 ― C#への「インターフェースのデフォルト実装」の導入(中編)
前回は一般論としてのインターフェースとその課題を見た。今回はC#にインターフェースのデフォルト実装を導入すると、どのようなコードが書けるようになるのか、導入するために必要な修正点などについて見ていく。
15. インターフェースを拡張する2つの手段 ― C#への「インターフェースのデフォルト実装」の導入(後編)
破壊的な影響を他に及ぼすことなくインターフェースの機能を拡張するには、デフォルト実装に加えて拡張メソッドも使用できる。今回はこれら2つの方法がなぜ必要なのか、それぞれが得意としている分野について詳しく見る。
16. C# 7のタプルが一般的なガイドラインに沿わずに書き換え可能な構造体である背景
C# 7.0で登場した新しいタプル(ValueTuple構造体)は、複数の値をひとまとめにして扱うのに便利なデータ構造だが、その実装は一般的な構造体のガイドラインに従っていない。なぜそうなっているのか、技術的背景を追う。