なんかC#6.0がそろそろ登場するらしい
書ける言語の数が両手で足りる人間が好きな言語を語るのもどうかと思うが、C#は好きな言語のトップ3には間違いなく入る。だけど悲しいことに、ここ1年ぐらいC#でコーディングする機会がなく、専らRubyとJavaScriptとVB(しかも自由に改行できない2008!)ばかり書いていたので知らなかったのだが、アンダース・ヘルスバーグ曰くC#6.0はコンパイラもC#で書き直して出すとのこと。
http://wesnerm.blogs.com/net_undocumented/2013/07/anders-on-c-60-at-build-2013.html
んで、更にググって見るとC#の開発者であるマッツ・トルゲルセンという人がなんか昨年の12月にC#6.0の導入を検討されている新機能を語ったという情報がある。
http://adamralph.com/2013/12/06/ndc-diary-day-3/#more
http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated
ここまでの情報を組み合わせると、もう今年の話なんだが、2014年にC#6.0(とVB2014?)が出るらしい。以下はほぼ転載気味で検討されている新機能を見てみる。
プライマリーコンストラクタ
クラス定義とコンストラクタを合体して書けるようになる模様。原文ではconstructorsとsがついてるのでこのシンタックスで複数定義できるっぽい。F#やScalaには既にある機能だとか。C#5.0まで
public class Point { private int x, y; public Point(int x, int y) { this.x = x; this.y = y; } }
C#6.0
public class Point(int x, int y) { private int x, y; }
Readonlyな自動実装プロパティの新記法
一つ疑問なのは、この記法の場合コンストラクタで実行時に値を変えることは可能なのだろうか。そうでない場合そもそもconst
に比べた場合のメリットが希薄なように思えてならない。C#5.0まで
private readonly int x; public int X { get { return x; } }
C#6.0
public int X { get; } = x;
静的クラスのusing
C#5.0まで現在の名前空間に静的メソッドを全て持ってこれるらしい。
string.IsNullOrEmpty(obj)
がIsNullOrEmpty(obj)
になるのは地味に嬉しい。原文ではメソッドに限定しているがメンバも持ってこれると助かるのだが…。
public double A { get { return Math.Sqrt(Math.Round(5.142)); } }
C#6.0
using System.Math; ... public double A { get { return Sqrt(Round(5.142)); } }
プロパティ定義式
悪くないんだけど、この記法でsetとgetの両方を定義することはできるのか?C#5.0まで
public double Distance { get { return Math.Sqrt((X * X) + (Y * Y)); } }
C#6.0
public double Distance => Math.Sqrt((X * X) + (Y * Y));
メソッド定義式
この例の場合は一行メソッドだから行数減ってインパクトあるけど、複数行のラムダ式になる場合はそもそも意味あるのだろうか…。C#5.0まで
public Point Move(int dx, int dy) { return new Point(X + dx1, Y + dy1); }
C#6.0
public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
可変長引数はIEnumerable型でも渡せるように
でも渡した先でどうせ配列に直すんじゃそれほど変わらないようにも思えるのだが…。C#5.0まで
public void Do(params int[] values) { ... } Do(someEnum.ToArray());
C#6.0
public void Do(params IEnumerable<Point> points) { ... } Do(someEnum);
モナド風ぬるぽチェック
関数型言語は全く知らないのでモナドが何かよく理解できないのだが、要はRails(≠Ruby)で言うhoge.try(:points).try(:first).try(:x)
みたいなことをやりたいのだと理解する。C#5.0まで
if (points != null) { var next = points.FirstOrDefault(); if (next != null && next.X != null) return next.X; } return -1;
C#6.0
var bestValue = points?.FirstOrDefault()?.X ?? -1;
ジェネリッククラスの型パラメーターの推論
これは確かに自明なんだから推論できるはずだ。ただ、いい加減メンバー変数にも型推論を入れて欲しいのだが…。C#5.0まで
public MyClass<T1, T2> Create<T1, T2>(T1 a, T2 b) { return new MyClass<T1, T2>(a, b); } var x = MyClass.Create(1, "X");
C#6.0
var x = new MyClass(1, "X");
out引数のインライン宣言
これは気になっていたので地味に嬉しいのだが、個人的にこのxって直感的にスコープが違うように脳が判断してしまうので、後の行で直接参照するのも少し気持ち悪い気がする。そもそもTryParse
がbool
を返すこと自体がおかしいんじゃないのか。C#5.0まで
int x; int.TryParse("123", out x);
C#6.0
int.TryParse("123", out int x);
ここまで見た感想として、個人的にC#3.0とC#4.0で大きく言語仕様が拡大されたのにC#5.0では変更点が拍子抜けする程少なかったので、細かいながらも色々と糖衣構文を盛り込もうとしているC#6.0は歓迎したいところではある。一方で「この程度か…」という気持ちもまた芽生えてしまう。ScalaとかC++とかC#より機能が多めとされている静的型付け言語もあるようだし、まだまだ他の言語からパクれる要素は残ってるのかもしれない。まあパターンマッチ導入以前に、いい加減switch
文のbreak;
必須を撤廃するとかして欲しいんだがなあ…。