我遇到这个简单代码的问题,我不明白为什么c#会这样做。
问题似乎是c#在列表中使用列表时使用Linq表达式引用而不是值。
在数字循环中,我根据列表选择数字,它们都存在,所以所有数字都应该添加到列表{1,2,3}中。
当您在控制台中看到数字循环中显示{1,2,3}的输出时,行为正常。
问题出现在列表的循环上,在这里似乎Linq只将最后一个数字添加到列表中,因此输出{3,3,3}。
我知道我不需要列表中的整数列表,但这只是为了证明这一点非常奇怪,这是一个已知的“错误”吗?
编辑:这似乎是它应该在5.0之前的c#中工作的方式。 在C#5.0(VS2012 +编译器)中,此行为已被修改为我期望的
static void Main()
{
var list = new List<IEnumerable<int>>();
var numbers = new[] {1, 2, 3};
var numbers2 = new[] {1, 2, 3};
foreach (var number in numbers)
{
var result = from s in numbers2
where s == number
select s;
Console.WriteLine(result.First()); // outputs {1,2,3}
list.Add(result);
}
foreach (var num in list)
{
Console.WriteLine(num.First()); // outputs {3,3,3}
}
}
输出
1 2 3 3 3 3
答案 0 :(得分:8)
此
list.Add(result);
不符合您的期望。它不会添加数字列表。 添加查询。查询按需执行 。因为,在最终输出循环number = 3
中,所有三个查询都返回3
。
如果要添加列表,请通过向其添加ToList
来强制立即执行查询:
list.Add(result.ToList());
答案 1 :(得分:2)
是的,众所周知。我相信它已在c#5修复。
您可以在foreach中声明一个值,然后在Console.WriteLine中使用该值来仅使用num的结束值来停止它。
请参阅此内容以获得更清晰的解释。 The foreach identifier and closures
答案 2 :(得分:2)
执行查询时, number == 3.
这是因为第一个foreach循环已经执行,而 number 的最后一个赋值实际上是3。
LINQ查询在必要时延迟执行(例如,当您调用ToList()
时)。
这不是一个奇怪的结果,这就是它的意思。
顺便说一下,在C#5.0(VS2012 +编译器)中,这种行为已被修改为你所期望的。
答案 3 :(得分:1)
只有在需要结果时才执行linq表达式。
所以
var result = from s in numbers2
where s == number
select s;
当需要result的值时,将执行。但是,如果要立即计算表达式,则需要从中获取结果并创建对象。
像
var result = (from s in numbers2
where s == number
select s).ToList();
如果你想看到一个正确的流程,那么在“from s in numbers2 ....”的行上设置一个断点,看看它什么时候被击中......
希望它有所帮助...