我有以下代码:
class Program
{
private static List<Member> members = new List<Member>
{
new Member() {m_FirstName = "Chiristopher", m_LastName="Harrison"},
new Member() {m_FirstName = "Jeremy", m_LastName = "Foster"},
new Member() {m_FirstName = "Stacey", m_LastName = "Mulcahy"}
};
static void Main(string[] args)
{
var result = (from m in members
where m.m_LastName.Length > 6
select m);
Console.WriteLine("** First Execution **");
foreach(var member in result)
{
Console.WriteLine(member);
}
members.Add(new Member() { m_FirstName = "Rian", m_LastName = "ThyTuhfadsl" });
Console.WriteLine("** Second Execution **");
foreach (var member in result)
{
Console.WriteLine(member);
}
}
}
当我建造它时: 安慰: **首次执行** Chiristopher Harrison 史黛西马尔卡希 **第二次执行** Chiristopher Harrison 史黛西马尔卡希 Rian ThyTuhfadsl
如果我调试,结果变量在第一个时有3个值,但它只打印两个值。为什么呢?
并且在第二个,是四个值。虽然,我不会重新键入任何代码
如果我输入
var result = (from m in members
where m.m_LastName.Length > 6
select m).toList();
在任何情况下只有两个值。
答案 0 :(得分:1)
因为linq查询被懒惰地评估了。大多数linq查询方法都返回一个Iterator
变量。迭代器仅在您使用foreach
调用迭代时执行某些方法,例如ToArray
或ToList
迭代结果并将它们添加到列表中。
答案 1 :(得分:1)
linq查询可以是几种类型,如.NET中所定义:
IEnumerable<T>
for linq-to-objects IQueryable<T>
for linq-to-sql ParallelQuery<T>
在您的情况下,您使用的是linq-to-objects,因此result
变量的类型为IEnumerable<Member>
。这被定义为一个可枚举的序列,在您实际枚举它之前,它不一定具体化。这就是这里发生的事情。请参阅my answer here,其中详细介绍了可用数据。
我们说该查询是懒惰评估的。第二次枚举它时,会重新评估它。如果您致电.ToList()
,您将只实现一次查询并获取一个列表,这将在两个枚举中产生相同的结果。
答案 2 :(得分:0)
这是“延迟执行”的一部分,您可以在线搜索。
在需要之前不会执行查询。 (只有当你迭代它时)。
'.tolist()'命令强制执行查询。
答案 3 :(得分:0)
这与linq查询的延迟评估有关。如果您在linq查询之后编写ToList()
,则会立即对其进行评估和实现。如果您不编写ToList()
,则仅在确实需要时才评估查询。
答案 4 :(得分:0)
在您的第一个代码示例中,您将枚举原始列表两次。
但是当您用上一个代码示例替换LINQ查询时,您可以复制原始序列。
LINQ方法ToList将序列的副本复制到List<T>
实例中。
因此,在这种情况下,您将枚举序列的副本两次,同时更改原始列表。
答案 5 :(得分:0)
if I debug, result variable has 3 values at the first,
除了其他人所说的内容,如果我正确理解你的问题,你所说的关于结果的3个值指的是source
属性还没有实现,因为它只是
private class WhereListIterator<TSource> : Enumerable.Iterator<TSource>
{
private List<TSource> source;
private Func<TSource, bool> predicate;
private List<TSource>.Enumerator enumerator;
所以你的代码是正确的