Visual Studio 2015が正式リリースとなり、いよいよC#6時代が幕を開けた。
async, awaitの時のような劇的な変化はないけれど、かゆい所に手が届いた感がある。
今回は、C#6で導入されたnameof 式と例外フィルター(when)を使うと、具体的にどう嬉しいかを考える。
nameof 式
変数やプロパティの名前を使いたい時、直接文字列を設定していたけれど、C#6からはnameofを使えばいい。
1 2 |
var iAmSam = "I am Sam"; Console.WriteLine(nameof(iAmSam)); // Writes iAmSam |
これはプロパティ名を取るのにも使える。
1 2 3 4 5 6 7 |
class Person { public int Age; } var he = new Person(); Console.WriteLine(nameof(he.Age)); // Writes Age |
nameofはnullチェックに使える
拡張メソッドを使って、変数のnullチェックをしているプロジェクトは多いと思う。
もし、変数がnullだったらArgumentNullExceptionを投げるだけの簡単なもので、例えばこういうの。
1 2 3 4 5 6 7 8 |
public static void CheckNull<T>(this T target, string targetName) where T : class { if (target == null) { throw new ArgumentNullException(targetName); } } |
一つ問題があって、ArgumentNullExceptionには変数の名前を渡してあげないといけないから、C#6までは、文字列を直接打ち込んで変数名を渡していた。しかし、これからはnameofがある!
1 2 |
var oldType = "old type"; oldType.CheckNull("oldType"); |
これが、こうなる↓
1 2 |
var newType = "new type"; newType.CheckNull(nameof(newType)); |
あとから変数名が変わったときにも対応できるからメンテナンス性があがりましたね。
例外フィルター (when)
try – catchで例外の型を指定して例外キャッチできていたけれど、もうちょっと細かいフィルタリングをしたかったので、これは実に嬉しい機能。
具体的には、whenに続けて条件式を書き、それがtrueなら例外をキャッチする。
1 2 3 4 5 6 7 8 |
try { throw new Exception("test"); } catch (Exception ex) when (ex.Message == "test") { Console.WriteLine("Error has occurred"); } |
したがって、あまり必要なケースはないけれど、例外オブジェクト以外のフィルターも設定できる。
1 2 3 4 5 6 7 8 9 10 |
var catchException = true; try { throw new Exception("test"); } catch (Exception ex) when (catchException) { Console.WriteLine("Error has occurred"); } |
例外フィルターを一括例外キャッチに使う
以前、TOACHの記事で、複数の例外を一箇所でキャッチするテクニックを紹介した。
[C#] 複数の例外(Exception)を一箇所で処理する方法
この記事の方法は純粋なエラー処理にフィルタリングが混じっていて完璧とは言えなかった。
そこで僕らのC#6。whenを使えば、厳密にフィルターとエラー処理を分けることができ、ネストも浅くできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
try { // Do something } catch (Exception ex) { if (ex is ArgumentNullException || ex is InvalidCastException || ex is AccessViolationException) { Console.WriteLine("Error has occurred!"); } throw; } |
これをwhenで書き直すと……
1 2 3 4 5 6 7 8 9 10 11 12 |
try { // Do something } catch (Exception ex) when ( ex is ArgumentNullException || ex is InvalidCastException || ex is AccessViolationException) { Console.WriteLine("Error has occurred!"); } |
いや〜美しいですね。
C#6は他にも便利な機能がたくさん。もっと知りたい方はこちらをどうぞ!