在foreach语句中执行LINQ是否更有效?

发布于 2025-02-05 10:00:16 字数 319 浏览 1 评论 0原文

这些陈述有同样的事情吗?

var listA = someList.TakeWhile(predicate);
foreach(var item in listA)
{
    /// perform code here
}

versus ...

foreach(var item in someList.TakeWhile(predicate))
{
    /// perform some code here
}

集合是先创建的,然后通过O(n^2)迭代?还是该集合迭代为其创建O(n)?

Do these statements do the same exact thing?

var listA = someList.TakeWhile(predicate);
foreach(var item in listA)
{
    /// perform code here
}

versus...

foreach(var item in someList.TakeWhile(predicate))
{
    /// perform some code here
}

Is the collection created first and then iterated through O(N^2)? Or is the collection iterated through as its being created O(N)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薄荷港 2025-02-12 10:00:17

@Jeremy Lakeman在评论中提供了正确的答案。

变量lista的类型在:

var listA = someList.TakeWhile(predicate);

is iEnumerable< t>,t是您集合的单个元素somelist的单个元素的类型。 take take方法的签名清楚地表明了这一点:

public static System.Collections.Generic.IEnumerable<TSource> TakeWhile<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,int,bool> predicate);

take take take文档页面

声明类型iEnumerable&lt; t&gt;的变量不会枚举它。
要列举iEnumerable,您必须明确地进行,如果 foreach 循环,或者使用它来产生新的实体集合,例如list字典等... ...

在(例如) tolist文档

tolist&lt; tsource&gt;(iEnumerable&lt; tsource&gt;)方法迫使
查询评估并返回包含查询的lt; t&gt;
结果。您可以将此方法附加到查询中,以获取
查询结果的缓存副本。 toarray具有相似的行为,但是
返回数组而不是list&lt; t&gt;

因此,在您的两个代码示例中,iEnumerable您构建的将在循环中仅列举一次。

另外:即使您在列举之前已经实现了收集:

var listA = someList
    .TakeWhile(predicate)
    .ToList(); // Notice the .ToList() call that forces the enumeration.

foreach(var item in listA)
{
    /// perform code here
}

它仍然是O(n)操作,而不是O(n^2)。
如果您从somelist集合中获取n个元素,则将用.tolist()呼叫一次枚举它们,然后在foreach loop中,总共2 x n,而不是n^2。

@Jeremy Lakeman provided the right answer in comments.

The type of the variable listA in:

var listA = someList.TakeWhile(predicate);

is IEnumerable<T>, T being the type of an individual element of your collection someList. This is clearly shown by the signature of the TakeWhile method:

public static System.Collections.Generic.IEnumerable<TSource> TakeWhile<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,int,bool> predicate);

as can be seen at the TakeWhile documentation page.

Declaring a variable of type IEnumerable<T> doesn't enumerate it.
To enumerate an IEnumerable, you have to do it explicitly, by enumerating it if a foreach loop for instance, or by using it to produce a new materialized collection, such as a List, Dictionary, etc... by calling methods such .ToList() or ToDictionary(), etc...

This is explicitly stated in the (for instance) ToList documentation:

The ToList<TSource>(IEnumerable<TSource>) method forces immediate
query evaluation and returns a List<T> that contains the query
results. You can append this method to your query in order to obtain a
cached copy of the query results. ToArray has similar behavior but
returns an array instead of a List<T>.

So in both your code examples, the IEnumerable you construct will be enumerated only once in the foreach loop.

Also: even if you had materialized your collection before enumerating it:

var listA = someList
    .TakeWhile(predicate)
    .ToList(); // Notice the .ToList() call that forces the enumeration.

foreach(var item in listA)
{
    /// perform code here
}

It would still be an O(n) operation, not an O(n^2).
If you take N elements from your someList collection, you will enumerate them once with the .ToList() call, and once in the foreachloop, for a total of 2 x N, not N^2.

小情绪 2025-02-12 10:00:17

两种形式都是相同的。根据Microsoft文档,查询(take the)直到其getEnumerator方法直接或foreach调用。

直到直接调用其getEnumerator方法或使用 for Visual C#或 for Visual C#或 for for for Visual C#或 for for for Visual C#或for for Visual C#或每个在Visual Basic中。

Both forms are same. According to Microsoft documentation the query (TakeWhile) won't execute until its GetEnumerator method is called directly or by foreach.

The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.

source

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文