ほげほげー

C#メインにプログラミング周りから日常のあれこれとかを不定期に書いていきます。

Visual Studio 2015 と Unity と

Visual Studio 2015 が Go Live になってもう結構経ちますね。

まぁでもどうせ Unity では C# の新機能使えないしなー関係ないね。
なんてことは無くて、今回の C# 6.0 で追加された機能は割とUnityでも使えちゃいます。

何故使えるのかは後述するとして、今回は Unity で C# 6.0 を使う方法を簡単にまとめていきたいと思います。

はじめに

C# 6.0 について知らないと話にならないですね。
詳しくは他のサイト見て頂くのが早いとは思いますが、一応簡単にまとめておきます。

それぞれの和訳は他のサイトに倣っています。(タブン)

C# 6.0

Null条件演算子(Null-Condition Operator)

昔はNull伝搬演算子(Null-Propagation Operator)と呼ばれていたヤツです。*1

. の代わりに ?. を使う事でnullチェックを行った上でメソッドやプロパティの呼び出しができるようになりました。
言葉で説明しても分かりにくいと思うので、コードを見てみましょう。

// 従来
if (hoge == null) return null;
return hoge.Hoge();

// C# 6.0
return hoge?.Hoge();

これらがほぼ同義になります。
元の変数がnullならそれが伝搬してnullを返却するようになります。

自動実装プロパティ初期化子(Auto-property initialization)

今までプロパティの初期化はコンストラクタ内で値をセットするか、
または private field を別途用意して予め値を入れておく必要がありました。

C# 6.0 ではそれがフィールドと同じように簡単に書けるようになりました。

これもやっぱりコードで。

まずは初期値を設定したプロパティ。

// 従来
private string _hoge = "default";
public string Hoge
{
    get { return _hoge; }
    set { _hoge = value; }
}

// もしくは
public string Hoge { get; set; }
public Constructor()
{
    Hoge = "default";
}

// C# 6.0
public string Hoge { get; private set; } = "default";

次に getter のみの自動実装プロパティ。

// 従来
public string Hoge { get { return _hoge; } }
private readonly string _hoge = "hoge";

// C# 6.0
public string Hoge { get; } = "hoge";

定型的で面倒くさいコードが若干シンプルになりますね。

本体が式の関数メンバ(Expression-bodied function members)

もっといい感じな言い回しは無いかしら。
名は体をちゃんとしっかり表現していますが。

さて、これは本体が1つの式で書ける関数、及びプロパティに利用可能な記法です。

コードを見て行きましょう。

// 従来
public string Hoge
{
    get { return Request["hoge"]; }
}

// C# 6.0
public string Hoge { get; } => Request["hoge"];

さっきの 自動実装プロパティ初期化子ラムダ式になっただけです。
が、これは関数にも適用可能なので若干違いますね。

また、自動実装プロパティ初期化子 ではプロパティに設定したインスタンスが保持されますが、
本体が式の関数メンバでは呼び出す度に記述した処理が実行されるので、
評価が一度で済むものに関しては前述の自動実装プロパティ初期化子を使うように。

そもそも役割が違いますし。

nameof 演算子

コード見たら一瞬。

// 従来
var className = "HogeClass";
var propertyName = "HogeProperty";
var fieldName = "hogeField";
var methodName = "HogeMethod";

// C# 6.0
var className = nameof(HogeClass);
var propertyName = nameof(HogeProperty);
var fieldName = nameof(hogeField);
var methodName = nameof(HogeMethod);
  1. typo の心配がなくなる
  2. Refactor による変更でいっしょに変わる
  3. コード解析の対象になる

シンプルなメリット。

文字列の挿入

スクリプト系の言語では割とよくある文字列内での式展開です。

今まではstring.Formatを使っていましたが、挿入箇所と挿入する変数の場所が離れるため、可読性に難がありました。

これを専用の構文を使うことで文字列内に直接挿入することが出来るようになるので、
積極的に利用していきたいですね。

// 従来
return string.Format("'{0}': '{1:D3}'", hoge.Key, hoge.Value);
return string.Format("'{0}': '{1}'", "key", dic["key"]);
return string.Format("{0}{{0}}", "hoge"); //=> "hoge{0}"
return string.Format(@"{0}
{1}", one, two);

// C# 6.0
return $"'{hoge.Key}': '{hoge.Value:D3}'}"; // フォーマット指定可能
return $"'key': '{dic["key"]}'}"; // 文字列リテラルも埋め込み可能
return $"{"hoge"}{{0}}"; // エスケープの仕方は同じ
return $@"{one}
{two}";

間には式も入れる事ができるので、単純な式は入れてみてもいいかも。

using static

static class を using することでクラス名を省略できるようになりました。

// 従来
System.Console.WriteLine("hoge");

// C# 6.0
using System.Console;
~ 中略 ~
WriteLine("hoge");

アナライザー

こいつ。

f:id:tyhe:20150610225751p:plain

Roslynを使ってコード解析したり整えたり定型的な何かを実施したり。

を、自前で実装することが出来るっぽいヤツです。

今まで挙げた機能の中で一番の目玉ですが全く調べて無い上に
それだけで記事がひとつ書けちゃうレベルな気がするので今回は紹介だけ。

具体的にはこんなの(from neuecc 先生)

Introduction to NotifyPropertyChangedGenerator

その他

めんどくさくなったので後は目次だけ。

インデックス初期化子

拡張メソッドのAddでコレクションを初期化

何故 C# 6.0 が Unity で使えるのか

今回導入された機能は全て今までの書き方を楽にするための糖衣構文なだけ、だからです。

つまり、コンパイル時に暗黙的に何らかの型に置き換わったり、
はたまた生成される中間言語に新しい命令が加わって居たり、
などということは無く、出力される中間言語としては今までと何ら変わらないからです。

ちなみに async/await も同様なので、async/await が使いたい方はこちらの記事も併せてお読み下さい。

[https://www.taihei.tips/entry/2016/04/05/Unity%E3%81%A7%E3%81%AE%E9%96%8B%E7%99%BA%E3%81%A7%E3%82%82_async/await%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86:embed:cite]

本題 Unity で C# 6.0 を使う

ようやく本題です。

Unity で C# 6.0 を使うには

C# 6.0 を使うには、Unity が生成するソリューション・プロジェクト内ではなく、
外部プロジェクトとしてプロジェクトを作り、そこで開発をします。
そのプロジェクト内に限り、C# 6.0 は利用可能です。

開発したものを使うには、ビルドして生成された dll を

/project/Assets/Dlls

配下に入れるだけです。

こうすることで、Unity が生成するソリューション・プロジェクト内から参照可能になります。

以上デス。(本題短い)

また何か思いついたことがあれば追記するかも。

次の記事は VS2015 と Unity を組み合わせた場合の落とし穴 の予定。

嘘つきましたすみません><

*1:個人的にはこっちの方がしっくり来るんですが。