switch文が嫌い

受託開発担当のRyuです。

最近C#で開発することが多いのですが、よく利用するswitch文がどうしても好きになれませんでした。

まずはこちらを。

	enum KSAD
	{
		Kore,
		Sore,
		Are,
	}

	void If(KSAD ksad)
	{
		if (ksad == KSAD.Kore)
		{
			Kore();
		}
		else if (ksad == KSAD.Sore)
		{
			Sore();
		}
		else
		{
			Are();
		}
	}

	void Switch(KSAD ksad)
	{
		switch (ksad)
		{
			case KSAD.Kore:
				Kore();
				break;
			case KSAD.Sore:
				Sore();
				break;
			default:
				Are();
				break;
		}
	}

お分かりいただけたでしょうか?
そう、switch文だとインデントが1段余分に深くなってしまうのです!!
このコード自体はどちらもサイクロマティックは同じなのですが、インデントが深いとどうしても複雑なコードというイメージが付き纏います。

	void Ififif()
	{
		if ()
		{
			if ()
			{
				if ()
				{
					// こういうイメージ
				}
			}
		}
	}

だからと言って全てをif文で書くというのも保守性の低下に繋がります。
ということでもやもやしながらもswitch文を書く日々が続いていました。
しかしある時Mono.Optionsというコマンドライン解析ライブラリを見てこんな方法もあるのかと驚きました。

	void Main(string[] args)
	{
		KSAD ksad;
		var os = new OptionSet()
		{
			{"Kore", v => ksad = KSAD.Kore},
			{"Sore", v => ksad = KSAD.Sore},
			{"Are", v => ksad = KSAD.Are},
		}
		
		os.Parse(args);
	}

Mono.Optionsはこのような記述でコマンドライン引数の解析ができます。
これを最初のswitch文のコードに適用するとこうなります。

	void Replace(KSAD ksad)
	{
		var dic = new Dictionary<KSAD, Action>()
		{
			{ KSAD.Kore, Kore },
			{ KSAD.Sore, Sore },
			{ KSAD.Are, Are },
		};

		dic[ksad].Invoke();
	}

見事にswitchもifも消えてしまいました。(内部では当然使われているんですが)
速度は当然落ちるので多用はできませんが、保守性を維持した上で簡潔な記述にできるこの書き方は色々応用が出来るのではと思います。
これを知ってから少しだけswitch文のことが好きになれました。