C# 6.0 新機能まとめ

この記事は下記のページを参考にしています。正式版 C# 6.0 のリリース時には機能が変更されている可能性があります。

[BuildInsider C# 6.0で知っておくべき13の新機能](http://www.buildinsider.net/small/csharplang/0600)

もくじ

    1 ★ 自動実装プロパティ用の初期化子
    2 ★ ラムダ式本体によるメンバーの記述
    3 ★ using static
    4 Null 条件演算子
    5 ★ 文字列補間
    6 nameof 演算子
    7 ★ インデックス初期化子
    8 例外フィルター
    9 catch および finally ブロック内での await
    10 パラメーターを持たない構造体コンストラクター
    11 コレクション初期化子内での Add 拡張メソッドの利用
    12 ？ オーバーロード解決の向上
    13 ？ #pragma によるユーザー定義コンパイラー警告の抑止

★ は便利そうな機能。？はめったに使いそうにない機能または一般のプログラマには関係なさそうな機能。

 
# 1 自動実装プロパティ用の初期化子

自動実装プロパティを定義するとき、値を初期化できるようになりました。今までできなかったのが不思議なくらいの機能です。

(例)

```csharp
public string Name { get; set; } = "Unknown";
```


# 2 ラムダ式本体によるメンバーの記述

従来はラムダ式は名前通り「式」でなければなりませんでしたが、メソッドやプロパティの本体の記述に使えるようになりました。これも今までできなかったのが不思議なくらいの機能です。

```csharp
public void Dump() => Console.WriteLine("({0},{1})", X, Y);
```


# 3 using static

これも便利な機能です。using static を使って定義すると、クラス名を指定せず、メソッドのみを記述できるようになりました。

```csharp
using static System.Console;
public class Test
{
   public static void Main()
   {
      WriteLine("Hello");  // Console. が不要。
   }
}
```

# 4 Null条件演算子

`?.` という演算子が追加されたそうです。null 以外のとき、値を変換するなどに使えそうですが、使う機会は少なそうです。

```csharp
// personsがnullであればnull、それ以外ならCount()の結果を返す
int? count = persons?.Count();
```

# 5 文字列補間

これは文字列に変数を埋め込む機能で、Perl や Ruby などのスクリプト言語ではポピュラーな機能です。文字列の先頭に $ を付けると変数が埋め込み可能になります。変数は { } で囲んで識別します。スクリプト系に慣れたプログラマならこれは頻繁に使う可能性がありますね。

```csharp
// 変数 Name を文字列に埋め込んでいる例
var s1 = $"Item name is {Name}";
```

# 6 nameof 演算子

nameof 演算子は式を与えて、その式の名前を文字列で返す演算子だそうです。nameof 演算子の主な目的は、変数名の文字列が必要な場所で今まで文字列を指定していたため、IDE のリファクタリング機能などが使えなかったところを使えるようにすることだそうです。

これはリファクタリングがありそうなシーンでは使っておいた方がいいかもしれませんが、使う機会は少なそうです。

```csharp
static void NameOf()
{
   string myName = "SakataGintoki";
   WriteLine(nameof(myName) + " is " + myName);  // "myName is SakataGintoki" と表示される。
}
```

# 7 インデックス初期化子

これは連想配列 (Dictionary<TKey, TValue>など) で簡単に初期化を行えるようにする機能です。これは使う機会が比較的多そうです。

```csharp
static void IndexInitializer()
{
  var dic = new Dictionary() { ["Hello"]="Kitty", ["Micky"]= "Mouse" };
  foreach (var key in dic.Keys)
  {
     WriteLine(key + " " + dic[key]);
  }
}
```

実行結果
`Hello Kitty
 Micky Mouse`


# 8 例外フィルター

構造化例外処理で catch 節の後に if 文を書いて例外のフィルタ処理ができるようになりました。例外処理を細かく行うときは便利かもしれませんが、比較的使う機会は少なそうです。

※ BuildInsider の記事では if が使われていましたが、現在は when に変わったようです。

```csharp
internal static void ExceptionFilter()
{
   try
   {
      File.Open(@"c:\\temp\IMG_5477.GIF", FileMode.Open);
   }
   catch (UnauthorizedAccessException)
   {
      WriteLine("不正アクセス例外を検出。");
   }
   catch (IOException ex) when (ex.Data == null)
   {
      WriteLine("IO例外を検出。追加情報はありません。");
   }
   catch (IOException ex)
   {
      WriteLine("IO例外を検出。" + ex.Message);
   }
}
```

# 9 catch および finally ブロック内での await

C# 5.0 では finally ブロック内で await ができなかったそうです。それが C# 6.0 からは可能になったという機能です。非同期処理を中心としたアプリでは使う可能性があるかもしれません。

# 10 パラメーターを持たない構造体コンストラクター

今までパラメータを持たない構造体のコンストラクタって NG だったんですね。C# 6.0 からは可能になったそうです。クラスでなく構造体を使う場合は便利かもしれません。

※ VS2015 RC 版では BuildInsider のサンプルがコンパイルエラーになりました。まだ、実装されないのか見送りになったのかわかりません。--> 見送りのようです。

# 11 コレクション初期化子内でのAdd拡張メソッドの利用

コレクション初期化子は実は内部で Add メソッドを呼び出しているそうです。この Add メソッドが実装されていないコレクション (例 Queue) ではコレクション初期化子が使えなかったそうですが、C# 6.0 からは拡張メソッドを定義すれば使えるようになるそうです。

```csharp
static void AddExtMethod()
{
  var q = new Stack() { 1, 2, 3 };
  WriteLine(q.Pop());
  WriteLine(q.Pop());
  WriteLine(q.Pop());
}

/// 
/// Stackの拡張メソッド Add
/// 
public static void Add(this Stack stack, int n)
{
   stack.Push(n);
}
```

# 12 オーバーロード解決の向上

これは(外部的)機能の追加でなく内部動作の改善のようなので C# プログラマには関係なさそうです。

# 13 #pragmaによるユーザー定義コンパイラー警告の抑止

C# プログラマが独自に追加した警告を抑止できるようになったそうです。これもめったに使いそうにない機能ですね。


-