次のようなことができます:
var result = myList.Concat(Enumerable.Repeat(default(int), 20)).Take(20);
そして、これを拡張メソッドに変えるのは簡単です:
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, T defaultValue)
{
return list.Concat(Enumerable.Repeat(defaultValue, count)).Take(count);
}
しかし、ここには微妙な落とし穴があります。これは、値の型、参照型の場合は完全に正常に機能します。null でない場合は、同じオブジェクトを複数回defaultValue
追加しています。これはおそらくあなたが望んでいないことです。たとえば、次のような場合:
var result = myList.TakeOrDefault(20, new Foo());
コレクションのパディングにの同じインスタンスFoo
を追加します。この問題を解決するには、次のようなものが必要です。
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, Func<T> defaultFactory)
{
return list.Concat(Enumerable.Range(0, count).Select(i => defaultFactory())).Take(count);
}
次のように呼び出します。
var result = myList.TakeOrDefault(20, () => new Foo())
もちろん、両方の方法を共存させることができるため、次のように簡単に設定できます。
// pad a list of ints with zeroes
var intResult = myIntList.TakeOrDefault(20, default(int));
// pad a list of objects with null
var objNullResult = myObjList.TakeOrDefault(20, (object)null);
// pad a list of Foo with new (separate) instances of Foo
var objPadNewResult = myFooList.TakeOrDefault(20, () => new Foo());