C#8 GA後のswitch式を見てみる
GAのタイミングで再確認してみるswitch式
後置き構文で読みやすいswitch式ですが、プレビュー時代は、以下の書き方をする必要がありました。
static IEnvironmentBuilder GetEnvironmentBuilder(string environmentName) { return environmentName switch { DefaultEnvironmentNames.Development => (IEnvironmentBuilder)new DevelopmentBuilder(), DefaultEnvironmentNames.DevelopmentRemote => new DevelopmentRemoteBuilder(), DefaultEnvironmentNames.Staging => new StagingBuilder(), DefaultEnvironmentNames.Production => new ProductionBuilder(), _ => throw new System.ArgumentException($"{nameof(environmentName)}") }; }
なぜか推論出来ない問題(@プレビュー時代)
return してるので普通に考えると、IEnvironmentBuilder を返却する式であることは推論できるはずなんですが、1番目で、 (IEnvironmentBuilder)とキャストして上げないと、コード解析で赤波線が出ていました。(逆に最初に書きさえすれば、2番目以降はIEnvironmentBuilder を実装したオブジェクトを設定してあげていれば大丈夫でした。)
なんか不格好だなーと思っていたんですが、.NET Core 3対応を行っていくタイミングで、このキャスト部分がコード解析で、「冗長だぞ!」って言われるようになっていることに気づきました。
return してるときは、戻り値から推論してくれるように改善されているようです。なので今は、
static IEnvironmentBuilder GetEnvironmentBuilder(string environmentName) { return environmentName switch { DefaultEnvironmentNames.Development => new DevelopmentBuilder(), DefaultEnvironmentNames.DevelopmentRemote => new DevelopmentRemoteBuilder(), DefaultEnvironmentNames.Staging => new StagingBuilder(), DefaultEnvironmentNames.Production => new ProductionBuilder(), _ => throw new System.ArgumentException($"{nameof(environmentName)}") }; }
で大丈夫。
varで受ける場合
varで受ける場合は、いつもの型推論の制約で、抽象的な型で受けられません。なのでこうなります。
なので、varで受け取る場合に、抽象的な型で受け取りたい場合はキャストが結局必要です。
static IEnvironmentBuilder GetEnvironmentBuilder(string environmentName) { var environmentBuilder = environmentName switch { DefaultEnvironmentNames.Development => (IEnvironmentBuilder) new DevelopmentBuilder(), DefaultEnvironmentNames.DevelopmentRemote => new DevelopmentRemoteBuilder(), DefaultEnvironmentNames.Staging => new StagingBuilder(), DefaultEnvironmentNames.Production => new ProductionBuilder(), _ => throw new System.ArgumentException($"{nameof(environmentName)}") }; return environmentBuilder; }
ローカル変数で受ける場合
varで受ける場合~の話と、推論の話で、もう予想はつくと思いますが、ローカル変数でswitch式を受ける場合はキャストは不要です。
static IEnvironmentBuilder GetEnvironmentBuilder(string environmentName) { IEnvironmentBuilder environmentBuilder; environmentBuilder = environmentName switch { DefaultEnvironmentNames.Development => new DevelopmentBuilder(), DefaultEnvironmentNames.DevelopmentRemote => new DevelopmentRemoteBuilder(), DefaultEnvironmentNames.Staging => new StagingBuilder(), DefaultEnvironmentNames.Production => new ProductionBuilder(), _ => throw new System.ArgumentException($"{nameof(environmentName)}") }; return environmentBuilder; }
switch式、後置き構文なこともあって、switch ステートメントよりもずいぶん読みやすくなりました。 使える時には積極的に使っていきましょう。