C#6.0時代のUnity

## はじめに
Unity2017のベータが公開されましたね！(これを書いている4月13日現在 Unity 2017.1.0b1 https://unity3d.com/jp/unity/beta#downloads）
なんといっても目玉は.NET 4.6が正式に対応！

覚えておいて損がないものは損が無いので覚えておきたいですし、今後.NET 4.6対応で書かれたソースコードもバンバン世に出てくるはずなので、使わないまでも読めるようになっておく必要はあるかと思います。

何ができるようになるのか、何に気を付けなくてはいけないのか。　ちょっと調べてみました。

## 下準備
.Net 4.6対応！ とはいっても、まだ試験導入的な立ち位置なので、最初の設定では使えず、PlayerSettingsを変更する必要があります。

まず、Scripting Runtime Version
![image](https://qiita-image-store.s3.amazonaws.com/0/37184/c4cd20c0-de38-0db6-3f70-4b56fcd43b95.png)
おお。　**.NET 4.6 Equivalent** がありますね！

そして、Api Compatibility Levelを.NET 4.6に・・・。
![image](https://qiita-image-store.s3.amazonaws.com/0/37184/5841f212-7667-feab-f6ac-8cc3f0c30eb0.png)
あるぇー？。

ってなりますが、ちゃんと再起動しろって英語で書いてありますね。
ScriptingRuntimeVersionを.Net4.6に変更して、Unityを再起動したところちゃんと4.6の項目が出てきました。
![image](https://qiita-image-store.s3.amazonaws.com/0/37184/0cb072a5-b497-0b63-dde1-85c82826ba0c.png)

これで、Unity側はC#6.0相当までビルドが通ります。通ります。が、少なくとも64bit版のUnity2017から生成されるVisualStudioのslnファイルにはがっつりLangVersionに**4**
って書かれてしまっているので、VisualStudio側でソースコードにC#6の機能を書くと
![image](https://qiita-image-store.s3.amazonaws.com/0/37184/1d60b06a-e6f7-e9c2-4b2f-f492f8c222ae.png)
と言われてエラーになってしまうっぽいです

そんなときは迷わずcsprojをメモ帳などで開いて
`    <LangVersion Condition=" '$(VisualStudioVersion)' != '10.0' ">4</LangVersion>`
の中の**4**を**6**に変えてあげるとVisualStudio上でもエラーが消えます。（いつか直るのかな・・・）

----
**2017/04/19 追記**
改めて詳しく調べてみた感じだと、Visual Studio 2017 Tools for Unity がうまくないっぽいです。
https://marketplace.visualstudio.com/items?itemName=SebastienLebreton.VisualStudio2015ToolsforUnity
を改めてインストールした後、UnityのEdit→Preferences...→External Tools→External Script Editorを
![image](https://qiita-image-store.s3.amazonaws.com/0/37184/44ba7eb1-a9df-45ca-41d2-59d5ed6218b5.png)
**Visual Studio 2015** にしたところ、ちゃんとしたcsprojファイルが吐き出されてました。まぁ、2017もいつかきっとなおるでしょう。
*追記終了*

---


さて。これでC#が6.0相当になりました。
いままでがC# 4.0相当だったので、新たにC#5.0の機能とC#6.0の機能が使えるようになります。

C#6.0新機能（抜粋）

- 文字列挿入
- オートプロパティ（拡張）
- expression-bodied
- null 条件演算子
- nameof 演算子

C#5.0新機能（抜粋）

- 非同期処理(async await)
- Caller Info Attribute

##積極的に使っていってもよさそうなもの
###1. 文字列挿入

今までは変数の中身を含んだ文字列を生成する場合、`+`で連結するか、

```csharp
string.Format("ほげほげ{0}です。",data);
```

のようにstring.Formatを使っていたところ、これからは**$** をダブルコーテーションの前に置くことで以下のように書くことができるようになります。

```csharp
var str = $"ほげほげ{data}です。";
```

この**{～}**に式や変数を置くことで文字列に直感的に埋め込むことができるんですねー。　便利。

なお、改行や￥をエスケープせずに使いたい場合に`@`を使いますが、この`$`と一緒に使いたい場合は

```csharp
var str = $@"ほげほげ
ほげ
ほげげ
{data}
ほほほげげげ\";
```

です。

```csharp
@$"~~~~";
```

ではエラーになってしまうので要注意です。

###2.expression-bodied
えくすぷれっしょんぼでぃ です。かっこいい名前です。

`=>`を使ってメソッドやプロパティの実装が書ける感じです。

```csharp
public int Data => func();
```

こう書くと

```csharp
public int Data{
    get{
        return func();
    }
}
```
と書いていたのと同じになります。短くなりましたね。
もし、`func()`が

```csharp
private int cnt = 0;
private int func(){
    return cnt++;
}
```

のように呼び出すたびに戻り値が0→1→2→3と増えるメソッドだったとして、

```csharp
//expression-bodied
public int Data => func();

void Start(){
    Debug.Log($"Data={Data}");
    Debug.Log($"Data={Data}");
    Debug.Log($"Data={Data}");
    Debug.Log($"Data={Data}");
}
```

とすれば、毎回Dataがgetされるたびにfuncが呼ばれるので

>Data=0
Data=1
Data=2
Data=3

という出力になります。

ちなみに、

```csharp
private int func(){
    return cnt++;
}
```
もexpression-bodiedで

```csharp
private int func() => cnt++;
```
と書けますが、こっちはあんまり使ったことないです。

###3.Caller Info Attribute
こんなクラス（メソッド）を作れます。

```csharp
public static class Log
{
    public static void DebugThrow(string message="",
        [CallerFilePath] string file = "",
        [CallerLineNumber] int line = 0,
        [CallerMemberName] string member = "")
    {
        Debug.Log($"{file}:{line}-{member}\t{message}");
    }
}
```

`[CallerFilePath]`を付けておくと、自動で呼び出し元のファイルパスがセットされます。
`[CallerLineNumber]`は呼び出し元の行番号
`[CallerMemberName]`は呼び出し元メソッドがそれぞれセットされます。

具体例としては、よくやるやつで実機でブレークが張れないような状況でよくわからないが呼ばれないメソッドがある。なんでだろう？

みたいなときに

```csharp
var cnt = 0;

Debug.Log("来たよ:" + cnt++);
処理1();
Debug.Log("来たよ:" + cnt++);
処理2();
Debug.Log("来たよ:" + cnt++);
処理3();
Debug.Log("来たよ:" + cnt++);
処理4();
```

みたいに1行ずつDebug.Log仕込んでどこまで処理が進んだか見る。　みたいなことをやるわけです（やりません？）

これって、cntがどんどん++されていくので、２０～３０あると
「あれ？"来たよ:15"で処理が止まってるけど、15番目ってどれかわからん」
と、指差し確認しながら1行1行数えるハメになるのです。　つらみ。

先ほどのクラスを作っておいて

```csharp
Log.DebugThrow();
処理1();
Log.DebugThrow();
処理2();
Log.DebugThrow();
処理3();
Log.DebugThrow();
処理4();
```
のように`Log.DebugThrow();`を書くだけで、呼び出し元のファイル名、行番号、メソッド名が出力されるので、もう指差し数える日々ともおさらばです。（ステップ実行すれば良いという正論は正論です）

なお、この`[CallerFilePath]`や`[CallerMemberName]`アトリビュートを指定した引数にファイル名やメンバ名を指定しているのは誰かという話で。
これはプログラム実行時に動的にファイルパスやメンバ名を取得しているわけではなく、ビルド時点ですべて定数として引数に渡されるんだそうで実行時コストは特にかかっていないのだとか。素敵です。

###4.オートプロパティ（拡張）
まず、

```csharp
public int Data{set;get;}
```

は
実際には

```csharp
private int _data;
public int Data{
    set{
        _data = value;
    }
    get{
        return _data;
    }
}
```

の意味なわけで、この時点で大分省略されているわけです（自動で作成される変数名は_dataではないと思います。便宜上。ね。）
そして、このDataの初期値をセットしたい。さらに言えば外からセットされたくない。　みたいなことが多くて。
今までは

```csharp
public int Data{private set;get;}
//コンストラクタ的なところ
Data = 100;
```

みたいにしてたわけです。
しかーし、UnityのGameObjectはコンストラクタが記述できないので、それこそ泣く泣くあえて実変数を宣言して

```csharp
private int _data = 100;
public int Data{
    get{
        return _data;
    }
    private set{
        _data = value;
    }
}
```

とやることに。辛い歴史。（StartやAwakeに書いてもいいけれど、初期化順番などで意図しない内容になっていることが時々ある。）

それが、C#6から初期値をプロパティにもセットできるようになりました。そのため、↑の処理は

```csharp
public int Data{private set;get;} = 100;
```

の1行に集約されます。素敵。

##使いどころが難しいもの
###1.null 条件演算子
メンバを参照する際に`.`を使うわけですが、`?.`という演算子が追加されました。

例えば、以下のようなプログラムがあったとして

```csharp
class TestData{
    public int value = 100;
}

public class TestDataUser : MonoBehaviour
{
    TestData _testData;

    void Start()
    {
        Debug.Log($"testData:{_testData.value}");
    }
}
```
これは実行時にエラーになります。
なぜなら_testDataをセットしておらずnullなので、valueの参照に失敗するからです。よくありますね。

対処法としては**nullチェック入れようぜ**。となるので

```csharp
public class TestDataUser : MonoBehaviour
{
    TestData _testData;

    void Start()
    {
        if(_testData != null)
        {
            Debug.Log($"testData:{_testData.value}");
        }
        else
        {
            Debug.Log("testData:nullだよ");
        }
    }
}
```
なんてことをよくやりますね。
このnullチェックして、中身が入っていたら～～～というのは非常によくやります。

これをちょっと減らすことができるのが`?.`です。

```csharp
        Debug.Log($"testData:{_testData?.value}");
```

こう書くと、これはエラーにならず、
>testData:

と出力されます。（空白はnull。）

この`?.`は左辺がnullの場合には例外にはならず、結果をnullにしてくれます。
なので、今回のようにintのメンバーにアクセスしようとしている場合は、nullの可能性が出てくるのでvalueはintではなくint?ということになります。

さらに `??` 演算子を使うのが多分常套手段で

```csharp
        Debug.Log($"testData:{_testData?.value.ToString() ?? "nullだよ"}");
```

_testDataがnullの時点で?.の機能でnullが返却され、??の左辺がnullになるので、"nullだよ"が返却される。

とか書けるわけです。

また、nullになる可能性があるので、代入式の左辺などには使えないです。

```csharp
_testData?.value = 0;
```
これは、testDataがnullの場合は`null = 0;`になっちゃうので、まぁ無理だよね。という話。

これ、個人的には非常にタイピング削減になるので良い新機能だとおもってるんですが、**Unityで使うとなると話は別**

これまた有名な話ではありますが、Unityの様々なクラスの基底クラスになっているObjectクラスは`static implicit equals(Object o1,Object o2){~~}`みたいな感じで等値演算子が魔改造されており、nullと比較するときだけ**参照がnullかどうかをあらわすのではなく、死んでいるかどうかを表す**ようになってます。

なのでnull 条件演算子と話がちょっとずれますが、Unityで指定のコンポーネントが存在したらそのまま返す（例えばImage)。なかったら追加して作って返却。

というのをやりたい場合に普通にC#的に書くと

```csharp
    private Image _image = null;
    public Image Image
    {
        get
        {
            return _image ?? (_image = gameObject.AddComponent<Image>());
        }
    }
```

なーんて書きたくなるんですが、ダメだったりするのです。
意味が違うのです。(??はEqualsメソッドと違ってオーバーロードされていない。というかできない（？））

```csharp
return _image != null ? _image : (_image = gameObject.AddComponent<Image>());
```

が正しいことになります。
これは`?.`も同じで、Object継承のクラスに対しては気を付けないと**nullチェックなのか、生死判定なのか**で全然意味が違ってきたりして辛くなる事が予想されます。

少なくとも安心して使えて使う機会が多そうなのはActionによるイベントコールバックのような処理の場合。

```csharp
    public event Action onDead;
    private void OnDestroy()
    {
        onDead?.Invoke();
    }
```
UnityのObjectとは無関係なので大いに使って結構です。

##使えるんだけど、今回書ききれなかったもの
###async await
~~超強力なんですが、coroutine（コルーチン）に慣れてしまっていたり、UniRXを使ってい るような人にわかりやすくメリットや、同居を示せる自信がないです。（TaskCompletionSource祭りになるような。）
むしろこっちが本題なのでいつか書きます。~~

続き書きました
[Unity2017で始めるTask(async～await)](http://qiita.com/divideby_zero/items/b6bbcc35aef08e1d7d3e)