負け犬プログラマーの歩み

負け組だった人間が今一度PGとして人生の飛躍を模索するも加齢と共に閉ざされる未来に直面しているブログ。

なんかC#6.0がそろそろ登場するらしい

書ける言語の数が両手で足りる人間が好きな言語を語るのもどうかと思うが、C#は好きな言語のトップ3には間違いなく入る。だけど悲しいことに、ここ1年ぐらいC#でコーディングする機会がなく、専らRubyJavaScriptVB(しかも自由に改行できない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って直感的にスコープが違うように脳が判断してしまうので、後の行で直接参照するのも少し気持ち悪い気がする。そもそもTryParseboolを返すこと自体がおかしいんじゃないのか。
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;必須を撤廃するとかして欲しいんだがなあ…。