switch式• これまで(switchはステートメントだけ)int y;switch(e){case 明治: y = 1868; break;case 大正: y = 1912; break;case 昭和: y = 1926; break;case 平成: y = 1989; break;case 令和: y = 2019; break;default: throw new InvalidOperationException();}// y を使って何か• caseとか代入とかbreakとかが並んでつらい• ステートメントなので書ける場所に制約あり〇
32.
switch式• switchを式で書けるように(後置き switch+ =>)var y = e switch{明治 => 1868,大正 => 1912,昭和 => 1926,平成 => 1989,令和 => 2019,_ => throw new InvalidOperationException()};// y を使って何か〇
33.
switc式(注意点)• 優先度が変わる• a+ x switch { ... } みたいなのの意味が変わる• 今 : 比較演算子(< とか <= とか)と同じ辺り(かなり低め)• 予定 : 単項演算子の直後(かなり高め)• 型推論強化• 代入先からの推論or• 共通基底推論A x = y switch {… }を A 扱いAとBに共通基底Baseがあるときx switch { … => new A(), … => new B(), … }を Base 扱い〇
34.
再帰パターン• 例としてこんな型があるとして• プロパティ2個•プロパティを初期化するコンストラクター• プロパティから値を取り出すDeconstruct◎readonly struct Point{public int X { get; }public int Y { get; }public Point(int x, int y) => (X, Y) = (x, y);public void Deconstruct(int x, int y) => (x, y) = (X, Y);}
35.
再帰パターン• 使えるパターンが増えた• 対称性◎staticint M(object obj) => obj switch{Point _ => 1,_ => 0,};こういうのはC# 7.0からあるstatic int M(object obj) => obj switch{Point(1, 2) => 1,Point { X: 2, Y: 3 } => 2,Point _ => 1,_ => 0,};位置パターン(Deconstructを利用)プロパティ パターン破棄パターンvar p = new Point(1, 2) p is Point(1, 2)var p = new Point(x: 1, y: 2) p is Point(x: 1, y: 2)var p = new Point { X = 1, Y = 2) p is Point { X: 1, Y: 2 }コンストラクター/初期化子 位置パターン/プロパティ パターン
36.
再帰パターン• 名前通り、再帰的に書ける• 型が自明の時には() や {} だけで書ける• () と {} の混在もできる◎x is Line { A: Point (1, var a), B: Point (2, _) }var p = new Point(1, 2);p is (1, 2)p is (1, _) { Y: 2 }
null合体代入• よくあるキャッシュ処理の類• 複合代入??= で書けるようにpublic string Data => _data = _data ?? GetData();private string _data;private string GetData(){// 1度きりしか呼ばないけどものすごく重たい処理}public string Data => _data ??= GetData();private string _data;private string GetData(){// 1度きりしか呼ばないけどものすごく重たい処理}〇int x = 1;int? y = null;var z = y ??= x;16.1でちょっと変更ありそう• zはintかint?か• 16.0ではint?• 16.1ではint
46.
.NET Core 3.0/.NETStandard 2.1推奨非同期ストリーム: await/yield混在• 生成側: 非同期イテレーター△async Task<Page> GetPageAsync(){// ネット越しに取りたいので asyncawait Task.Delay(1); // 代用return new Page();}IEnumerable<string> GetTitles(Page page){foreach (var s in page.Sections)yield return s.Title;}非同期メソッド(C# 5.0) イテレーター(C# 2.0)async IAsyncEnumerable<string> GetTitlesAsync(){Page page;do{page = await GetPageAsync();foreach (var title in GetTitles(page))yield return title;} while (page.HasNext);}• awaitとyieldの混在• 戻り値はIAsyncEnumerable
47.
非同期ストリーム: await foreach/using•消費側: 非同期foreach• await foreachの語順• IAsyncEnumerable<T>に対して使える• (System.Collections.Generic名前空間)• 同期版同様、パターン ベース(同じメソッドさえ持っていれば任意の型に使える)△.NET Core 3.0/.NET Standard 2.1推奨await foreach (var title in GetTitlesAsync()){Console.WriteLine(title);}
48.
インデックス範囲構文• 整数インデックスを持つ型の一定範囲(range)得るための構文• x[^i]で Length - i 番目の要素参照• Index構造体(System名前空間)が作られる• Index i = ^1; みたいな変数定義も可能• x[i..j] で i(含む)からj(含まない)の範囲を参照• Range構造体(System名前空間)が作られる• Range r = 1..^1; みたいな変数定義も可能△.NET Core 3.0/.NET Standard 2.1推奨