从C#中的Enumerable中准确获取x值的最佳方法是什么。
如果我像这样使用Enumerable .Take():
var myList = Enumerable.Range(0,10);
var result = myList.Take(20);
结果将只有10个元素。
我想用默认值填充缺少的条目。
像这样:
var myList = Enumerable.Range(0,10);
var result = myList.TakeOrDefault(20, default(int)); //Is there anything like this?
C#中是否有这样的功能,如果没有,实现此目的的最佳方法是什么?
最佳答案
您可以执行以下操作:
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);
}
但是这里有一个微妙的陷阱。如果您的
defaultValue
不为null,则您多次添加同一对象,这对于值类型,对于引用类型来说将是完美的。可能是您不想要的。例如,如果您有: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());