時々「誰か、名前、頼む」って気分になりませんか?
クラス名やメソッド名の命名って、悩みますよね〜。特に、不特定多数の人が利用する前提がある基盤ライブラリの開発なんかやってると、本当にいいのか?と困ります。私はとりあえずきめておいて、3〜10日以内に自分で見て違和感があったらリネームするなんてことを平気でやっていますが、いつかはそれが可能じゃない段階になるのですよね。
ところで、key と value が交互に並んだリストから辞書を作成するような場合、定番パターンってあるんですかね? といって調べもせずに、
// よくあるクラス(構造体にするか迷った) class Tuple<T1,T2> { } class Tuple<T1,T2,T3> { } class Tuple<T1,T2,T3,T4> { } // 束ねるメソッド static IEnumerable<Tuple<TSource,TSource>> ToTuple(this IEnumerable<TSource> source); static IEnumerable<Tuple<TSource,TSource,TSource>> ToTuple(this IEnumerable<TSource> source); static IEnumerable<Tuple<TSource,TSource,TSource,TSource>> ToTuple(this IEnumerable<TSource> source);
ええ、戻り値だけが異なるオーバーロードは不可能なので、これはコンパイルできません。ちなみに最初は、Take() を呼ぶ前提もあったため、TakeDoubler(), TakeTripler() といった名前になっていたのですが、違和感がありすぎたんですね。とりあえず、5分ほど悩んだ結果として、今は
public class Tuple<T1,T2> : IDisposable { public static IEnumerable<Tuple<TSource, TSource>> ToTuple<TSource>(IEnumerable<TSource> source) { var e = source.GetEnumerator(); while (e.MoveNext()) { TSource first = e.Current; TSource second = e.MoveNext() ? e.Current : default(TSource); yield return new Tuple<TSource, TSource>(first, second); } } public static IEnumerable<Tuple<T1, T2>> ToTuple(IEnumerable<TSource> source, Func<TSource,T1> firstSelector, Func<TSource,T2> secondSelector) { foreach (var t in ToTuple<TSoure>(source)) yield return new Tuple<T1, T2>(firstSelector(t.First), secondSelector(T.Second)); } }
こんなかんじに、Tuple クラスのメソッドになっちゃいました。(実際には、もうちょっとコードは複雑です)
これで、冒頭の問題は、
var dict = Tuple<,>.ToTuple(source).ToDictionary(t => t.First, t => t.Second);
と、Enumerable.ToDictionary() を利用して2要素でも3要素でも1まとめにできるようになりましたとさ。