17. static void Main()
{
IEnumerable<T> twice<T>(T x)
where T : struct
{
yield return x;
yield return x;
}
var xs = twice(12.3);
}
Local Functions
Generics
yield
なんでもOK
関数内で
のみ使える
関数
18. static void Main()
{
var a = 1;
ref var d = ref PassThrough(ref a);
d = 2;
// (a, d) = (2, 2)
}
static ref int PassThrough(ref int b)
{
ref var c = ref b;
return ref c;
}
Ref Locals / Ref Returns
メモリ効率
向上
参照受け
参照返し
19. (int sum, int count) Tally(IEnumerable<int> list)
{
var s = 0; var c = 0;
foreach (var x in list)
{
s += x;
c++;
}
return (s, c);
}
(int a, int b) t = Tally(new []{ 1, 2, 3 });
Tuples
ValueTuple
の糖衣構文
多値戻り値
サポート
20. //--- タプル型のインスタンスを
var t = (123, "abc");
//--- 変数に分解
(int x, string y) = t;
(var x, var y) = t;
var (x, y) = t;
Deconstructions
入れ子もOK
任意の型を
分解可能
21. より狭い
スコープ
//--- 定数マッチング
var v = x is 123;
//--- 型マッチング
object x = "abc";
if (x is string v)
{
//--- 何か v を用いた処理
}
Type Switch - is -
より簡易で
厳密な判定
22. object x = 123;
switch (x)
{
case "abc":
break;
case int v when 100 < v: //--- v が 100 より大きいとき
break;
case int v: //--- v が 100 以下のとき
break;
}
Type Switch - switch -
より強力な
条件分岐
when 句での
条件設定
(case guard)
23. class Program
{
//--- ラムダ形式メンバーに
public string Name => throw new NotImplementedException();
public string SayHello() => throw new NotImplementedException();
//--- 条件演算子 / null 結合演算子に
public int ParseAsInt(string value)
=> int.TryParse(value, out var x)
? x
: throw new ArgumentException(nameof(value));
}
Throw Expressions
コンパクト
に書ける
24. class Program
{
//--- プロパティやインデクサのアクセサに
public string Property
{
get => "Getter Property";
set => Console.WriteLine(value);
}
//--- コンストラクタ / デストラクタにも
public Program(string text) => Console.WriteLine(text);
~Program() => Console.WriteLine("Destructor");
}
Expression-Bodied Everything
{ } を
より少なく