C# Enumerable.Take 带默认值

标签 c# .net linq ienumerable take

从 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());

关于C# Enumerable.Take 带默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31656460/

相关文章:

c# - EF Core 在迁移 (UP) 时将列数据从表移动到另一个表

c# - 使用 Distinct 将 SQL 查询转换为 Linq (c#)

c# - 创建和处理 XmlNodeList

c# - Dictionary 是否损坏或 GetHashCode() 应该仅基于不可变成员?

linq - 我可以在 LINQ 中使用递增计数变量吗?

c# - Firebird embedded 和 Entity Framework 6 出现 "Unknown data type"错误

c# - Wp8 - 从应用程序重定向并返回时,EventHandler 为 null

c# - JSIL与Script#与SharpKit

c# - 合并两个动态列表并覆盖值

c# - 按多列分组,就好像它是一列一样