【问题标题】:LINQ yield all elementsLINQ 产生所有元素
【发布时间】:2019-01-02 08:01:12
【问题描述】:

当我想让一个 IEnumerable 急切地实现/产生它的所有结果时,我通常使用 ToList() 像这样:

var myList= new List<int>();
IEnumerable<int> myXs = myList.Select(item => item.x).ToList();

我通常在锁定返回 Linq 查询结果的方法时这样做。

在这种情况下,我实际上对将集合变成列表并不感兴趣,而且我通常不想知道它的类型。我只是因为它的副作用而使用 ToList() - 产生所有元素。

例如,如果我将类型从 List 更改为 Array,我还必须记住将 ToList() 更改为 ToArray() 或遭受一些性能损失。

我可以做到foreach( var e in myList ) { },但我不确定这是否会在某个时候进行优化?

我正在寻找类似myList.Select(item =&gt; item.x).yield()的东西

最好的方法是什么?有没有办法简单地告诉一个 Linq 结果来产生比 ToList 更好的所有元素?

【问题讨论】:

标签: c# linq c#-7.0


【解决方案1】:

如果只是为了练习列表,并且不想构造或分配任何类型的数组,您可以使用Last(),它将简单地遍历所有元素,直到它到达最后一个(见source)。

如果您真的对结果感兴趣,在大多数情况下,您应该只是 use ToList() 而不要想太多。

如果您想稍后检索结果,则无法避免分配某种存储空间。没有具体类型的魔法IEnumerable&lt;T&gt; 容器;你必须选择一个,ToList() 是最明显的选择,开销低。

如果您不想等待它完成,请不要忘记ToListAsync()

【讨论】:

  • 这是该问题的正确答案,但我想知道该问题背后的 actual 问题是什么。也许是懒惰的评价?尝试使用结果时出现铸造问题?或者,源不是列表而是 EF、OData 实体或 SharePoint 列表?或者可能是 那些 结果与另一个查询的结果混合在一起?
  • 谢谢!最后不会做,因为我需要结果
  • @kofifus “如果您想稍后检索结果,则无法避免分配某种存储”是答案(如所要求的那样)。如果您仍然不满意您需要在问题中解释的部分,您打算如何避免。
  • John Wu - 虽然你似乎是唯一一个理解我的问题的人! :( 基本上我需要一个 Last() 来返回它运行的可枚举对象
  • 没有kofifus这样的东西。遍历数据源会破坏它,因为底层数据库连接被暴露为只进游标。如果你第一次没有缓存它,它就消失了。你能做的最好的就是ToList(),就像我们其他人一样。
【解决方案2】:

仅供参考,因为也许这就是问题

您不必在单行中编写 LINQ 操作,您可以进一步扩展它:

例如:

var myList = new List<T>();
var result = myList.Select(x => x.Foo).Where(x => x.City == "Vienna").Where(x => x.Big == true).ToList();

可以改写为:

var myList = new List<T>();

//get an IEnumerable<Foo>
var foos = myList.Select(x => x.Foo);

//get an IEnumerable<Foo> which is filtered by the City Vienna
var foosByCity = foos.Where(x => x.City == "Vienna");

//get an IEnumerable<Foo> which is futher filtered by Big == true
var foosByCityByBig = foosByCity.Where(x => x.Big == true);

//now you could call to list on the last IEnumerable, but you dont have to
var result = foosByCityByBig.ToList();

所以无论你的真正目标是什么,也许你可以改变你的路线

var myList= new List<int>();
IEnumerable<int> myXs = myList.Select(item => item.x).ToList();

到这里:

var myList= new List<int>();
IEnumerable<int> myXs = myList.Select(item => item.x);

然后以IEnumerable&lt;int&gt; 的身份使用myXs 继续您的工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多