Movatterモバイル変換


[0]ホーム

URL:


Logo

目次

C# 7.1

Ver. 7.1
リリース時期2017/8
同世代技術
  • Visual Studio 2017 Update 3 (15.3)
要約・目玉機能
  • C# 7.0のちょっとした改善

2017年8月、すなわち、C# 7.0のリリース(2017年2月)から半年足らずで C# 7.1 がリリースされました。

C# 7.0の頃から、目標としては C# のリリース サイクルの短縮を考えていました。多くの機能を2・3年に1度一気にリリースするよりも、細かく出せるものに関しては短いリリース サイクルで出したいという意図です。今回、(実質的に)初の「マイナー バージョンアップ」となる C# 7.1 が誕生しました。

( 一応、C# 1.1があったんですが、ほとんど使われない機能が2つ追加されただけなので、1.1があったこと自体あまり認知されていないものです。)

C# 7.1 は、Visual Studio 2017のリリース時期に間に合わなかった C# 7.0 の積み残しと言った感じの、小さい機能が4つほど追加されています。

非同期Main

Mainメソッドの戻り値にTaskクラス(System.Threading.Tasks名前空間)を使えるようになりました。以下のいずれかのオーバーロードであればエントリーポイントとして認識されます。

staticTask<int> Main()staticTask<int> Main(string[] args)staticTask Main()staticTask Main(string[] args)

詳しくは、「非同期Main」で説明します。

default 式

これまでも既定値を作るために、default(T)という構文がありましたが、型名Tの指定が煩雑でした。特に、名前の長い型に対してdefault(T)を使うと、かなりのうっとおしさがあります。

既定値を結構使って、かつ、名前が長い型というと、例えばCancellationToken構造体(System.Threading名前空間)とかです。以下のようなコードを書いたりします。

staticasyncTask DefaultExpression(CancellationToken c =default(CancellationToken)){while (c !=default(CancellationToken) && !c.IsCancellationRequested)    {awaitTask.Delay(1000);Console.WriteLine(".");    }}

これに対して、C# 7.1では、左辺(代入先)から推論できる場合に、(T)を省略してdefaultだけで既定値を作れるようになりました。例えば先ほどのコードは以下のように書き直せます。

staticasyncTask DefaultExpression(CancellationToken c =default){while (c !=default && !c.IsCancellationRequested)    {awaitTask.Delay(1000);Console.WriteLine(".");    }}

既定値自体や、default(T)の説明は「既定値」を参照してください。

タプル要素名の推論

タプルの要素名が、タプル構築時に渡した変数から推論できるようになりました。例えば以下のように、(x, y) と書くだけで、1要素目にx、2要素目にy という名前が付きます。(これまでだと、(x: x, y: y) と書く必要があった。)

var x = 1;var y = 2;var t = (x, y);// C# 7.0。t の要素には名前が付かないConsole.WriteLine(t.Item1);Console.WriteLine(t.Item2);// C# 7.1。(x, y) で (x: x, y: y) 扱い// t の要素に x, y という名前が付くConsole.WriteLine(t.x);Console.WriteLine(t.y);

詳しくは「タプル」で説明します。

ジェネリック型に対するパターン マッチング(型スイッチ)

C# 7.0でisswitchで型を見ての分岐ができるようになりました。しかし、ジェネリクスが絡む場合、例えば以下のようなコードはC# 7.0ではコンパイル エラーになっていました。

staticvoid M<T>(T x){switch (x)    {caseint i:break;casestring s:break;    }}

Tintstringとして処理できない」と言った旨のコンパイル エラーが出ます。

さらにいうと、以下のような需要が結構ありそうな場面でも、C# 7.0ではコンパイル エラーになりました。

classBase { }classDerived1 :Base { }classDerived2 :Base { }classDerived3 :Base { }// こういう、型制約付きのやつですら 7.0 ではダメだったstaticvoid N<T>(T x)whereT :Base{switch (x)    {caseDerived1 d:break;caseDerived2 d:break;caseDerived3 d:break;    }}

C# 7.0でも、以下のように、as演算子を使った場合にはちゃんとコンパイルできます。型スイッチは、内部的にはas演算子に展開される機能で、as演算子にできて型スイッチにできないことがあるのは不自然です。

staticvoid N<T>(T x)whereT :Base{    {var d = xasDerived1;if (d !=null) {return; } }    {var d = xasDerived2;if (d !=null) {return; } }    {var d = xasDerived3;if (d !=null) {return; } }}

そこで、C# 7.1では、上記コードのような、ジェネリックな型に対する型スイッチを使えるようになりました。(新機能というよりは、仕様漏れ・バグ修正の類です。)

パターンマッチング(型スイッチ)自体の説明に関しては「型スイッチ」を参照してください。

更新履歴

更新:言語バージョンの指定

[C#]

ファイル ベース実行

[C#]

C# 14.0 の新機能

[C#]

更新:[雑記] オーバーロード解決

[C#]

型の分割定義 (partial)

[C#]

ブログ

C# 14 の破壊的変更点(First-class Span)

ファイナライザー

文字列リテラルを data セクションに UTF-8 で書き込む案

nameof(T<>)

First-class な Span 型


誤字等を見つけた場合や、ご意見・ご要望がございましたら、GitHub の Issues まで気兼ねなくご連絡ください。

[8]ページ先頭

©2009-2025 Movatter.jp