再入門C＃：条件分岐

今度は分岐について書いてみたいと思います。分岐に関しては `if` `三項演算子` `while` `switch` 等が使えますが、自分が良く理解していない部分として、`is`の構文の書き方、null チェックの方法、合体演算子あたりがあやふやなので試してみたいと思います。`switch`はパターンマッチ機能強化が大きくあるので、次回以降に譲ります。‘

例によって自分のためのブログなので、読みたい人は是非こちらのブログが最強なので、お読みください。本記事もほとんど参照しています。（自分のための学習ノートみたいなものです）
* [is, switch の拡張（型スイッチ）](https://ufcpp.net/study/csharp/datatype/typeswitch/?p=1)

# is 演算子

変数の型がマッチする場合に、何か処理を行いたいときは次の書き方が可能です。

```C#
型をしらべたい変数 is 型　新しい変数
```
具体的にはこんな感じで使います。

```C#
if (obj is string) Console.WriteLine("String");
```

## 型変換
型を調べたいとき、大抵はキャストなどを行いますが、クールな書き方はできるでしょうか？ ダウンキャストは推奨されていないので、通常は、`as`演算子を使います。ただ、Nullチェックは必要になります。

```C#
            var s = obj as string;
            if (s != null)
            {
                Console.WriteLine($"string #{s.Length}");
            }
```

C# 7 からは次の構文が使えます。知らんかった。カッコいい。新しく定義した変数から値をとることができます。ちなみに、`null` が来た場合は、`false` になります。だから、Nullじゃないときだけ実行したいときはこの方法が使えます。

```C#
            if (obj is string str) // C# 7 Notation
            {
                Console.WriteLine($"string #{str.Length}");
            }
```
## Null の扱い
様々な書き方ができますが、各パターンで振る舞いが異なります。`is` はNullは許容しません。 varパターンでは、Nullを許容します。再帰パターン `{ }` はNullを許容しません。

```C#
            string x = null;
            if (x is string) // through the case of null
            {
                Console.WriteLine("null is not string. This line will never be executed.");
            }
            if (x is string) Console.WriteLine("Never pass");
            if (x is var _) Console.WriteLine("Will pass");
            if (x is { }) Console.WriteLine("Never pass");  // recursive pattern is not match null
```

ちなみに、varパターンと再帰パターンは、パターンマッチングの構文です。下記は var パターンの例で、Nullを含めてすべてのパターンにマッチしますが、マッチするときに、変数に値をアサインしてくれます。ちなみに、このマッチは、Deconstruct メソッドを利用して値を取得するようです。

```C#
            string y = "abc";
            if (y is var z) Console.WriteLine($"S value is {z}");
```

他に再帰パターンですが、まさにパターンマッチの構文です。`{ }` でマッチさせると、Nullは許容しません。このパターンは次のような例で使えます。かなり強力なパターンマッチですね。再帰パターンに関してはこのブログもいい感じです。[C#8.0までに再帰パターンに馴染んでおく](https://qiita.com/muniel/items/ff58cf374851f67b34d7)。かなりパターンマッチングは深い感じなので今回のブログではさっと触れるだけで次回以降に掘り下げていきます。

```C# 
        private static void Main(string[] args) {
            Console.WriteLine($"0: {RecursiveDemo(0)}");
            Console.WriteLine($"3: {RecursiveDemo(3)}");
            Console.WriteLine($"Point(1,3): {RecursiveDemo(new Point(1,3))}");
            Console.WriteLine($"Point(2, 4): {RecursiveDemo(new Point(2, 4))}");

        }

        public class Point
        {
            public int X { get; set; }
            public int Y { get; set; }
            public Point(int x = 0,  int y = 0) => (X, Y) = (x, y);
            public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
        }

        private static int RecursiveDemo(object obj) => obj switch
        {
            0 => 1,
            int i => 2 * i,
            Point(1, _) => 4,
            Point { X: 2, Y: var y } => y,
            _ => 0
        };
```


### 結果

```
0: 1
3: 6
Point(1,3): 4
Point(2, 4): 4
```

# Null と　空文字判定

下記のがおなじみですが、スペースでもTrueになるメソッドもあります。

```C#
            if (string.IsNullOrEmpty(x))
            {
                Console.WriteLine($" {x} is : null or empty.");
            }
```

しかし大抵の場合は、合体演算子　`??` を使うほうがオシャレ度が高くなります。Nullの場合だけデフォルト値が差し込めます。

```C#
            Console.WriteLine($" default: {x ?? "default"}");
```

ちなみに、オブジェクトのメソッドを呼びたいとき、こんな書き方もできますね。Nullチェックのifがたくさんあるのは冗長なので、こちらの方がいい感じだと思います。

```C#
            Point a = null;
            Console.WriteLine($"{a?.X ?? 0}");
```