35. バグの例1: defaultリテラル(C# 7.1)
void M(int? x = default) { }
int?の規定値はnullなので、当然、nullであ
るべき
• VS 15.3(リリース時点) : 0になってた
• VS 15.4(修正版) : nullに
36. バグの例2: in引数(C# 7.2)
// 2変数、既定値付き
static void M(in int x = 0, in int y = 0) => WriteLine(y);
// 1変数だけ値を渡す
static void Main() => M(1);
yには0が入ってほしい
• VS 15.5(リリース時点) : なぜかnull参照
例外発生
• VS 15.6で修正
37. バグの例2: in引数(C# 7.2)
class X
{
// クラスに対して in 引数
static void S(in X x) => WriteLine(x.ToString());
// in 引数相手に this を渡す
void M() => S(this);
}
• VS 15.5(リリース時点) :
ExecutionEngineException発生
• VS 15.6(修正版)で修正
51. C# 7.3: オーバーロード解決の改善
static void M<T>(this T x) where T : class { }
static void M<T>(this ref T x) where T : struct { }
static void X(string s, int i)
{
s.M();
i.M();
}
前までは呼び分けできな
かった
型制約違い
52. C# 7.3: ジェネリック型制約の追加
static void E<T>(this T x)
where T : System.Enum { }
static void D<T>(this T x)
where T : System.Delegate { }
static void U<T>(this T x)
where T : unmanaged { }
列挙型だけを受け付
ける
デリゲート型だけを受け
付ける
ポインター化可能な型だけを受け
付ける
55. C# 8.0: null許容参照型
int M(string s)
{
return s.Length;
}
int N(string? s)
{
var x = s.Length;
if (s == null) return -1;
return s.Length;
}
単にこう書くと非
null
参照型でも、?でnull許容
に
nullチェックがないので
警告
nullチェックより後なの
でOK
既存コードを壊さないために
• オプションでモード切替可能
に
• null、非null、「未指定」
• 既存コードは「未指定」扱
いでコード解析する
56. C# 8.0: 再帰パターン
int M(object obj)
{
switch (obj)
{
case int i: return i;
case string s: return s.Length;
case Point (var x, var y): return x * y;
case Point { X : var x, Y : var y }: return X * Y;
}
throw new IndexOutOfRangeException();
}
int M(object obj)
=> obj switch
{
case int i => i,
case string s => s.Length,
case Point (var x, var y) => x * y,
case Point { X : var x, Y : var y } => X * Y,
_ => throw new IndexOutOfRangeException()
};
switch式
57. C# 8.0: Range
var array = new[] { 1, 2, 3, 4, 5 };
var x = array[1..3]; // 1以上、3未満
var x = array[1..^1]; // 1~末尾から1
0 1 2 3 4
{ 1, 2, 3, 4, 5 }
0 1 2 3 4
{ 1, 2, 3, 4, 5 }
58. C# 8.0: async stream
async IAsyncEnumerator<int> MAsync()
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(1);
yield return i;
}
}
foreach await (var x in MAsync())
{
}