C# 为什么c Linq在包含列表的列表中使用引用而不是值
我对这个简单的代码有问题,我不明白为什么c会这样 问题似乎是c在列表中使用列表时使用Linq表达式引用而不是值 在数字循环中,我根据列表选择数字,它们都存在,因此所有数字都应添加到列表{1,2,3} 当您看到控制台的输出时,行为正常,它在数字循环中显示{1,2,3} 问题在列表的循环中,在这里,Linq似乎只将最后一个数字添加到列表中,以便输出{3,3,3} 我知道我不需要在列表中列出int,但这只是为了证明一点,这很奇怪,这是一个已知的bug吗 编辑:在5.0之前的c语言中,它似乎就是这样工作的。 在C 5.0 VS2012+编译器中,此行为已修改为我所期望的C# 为什么c Linq在包含列表的列表中使用引用而不是值,c#,linq,list,C#,Linq,List,我对这个简单的代码有问题,我不明白为什么c会这样 问题似乎是c在列表中使用列表时使用Linq表达式引用而不是值 在数字循环中,我根据列表选择数字,它们都存在,因此所有数字都应添加到列表{1,2,3} 当您看到控制台的输出时,行为正常,它在数字循环中显示{1,2,3} 问题在列表的循环中,在这里,Linq似乎只将最后一个数字添加到列表中,以便输出{3,3,3} 我知道我不需要在列表中列出int,但这只是为了证明一点,这很奇怪,这是一个已知的bug吗 编辑:在5.0之前的c语言中,它似乎就是这样工作
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}
}
}
输出
一,
2.
3.
3.
3.
三,
这个
没有达到你的期望。它不添加数字列表。它添加了一个查询。查询是按需执行的。因为,在最终的输出循环number=3中,所有三个查询都返回3
如果要添加列表,请通过将ToList追加到列表中,强制立即执行查询:
是的,它是已知的。我相信它在C5中是固定的 您可以在foreach中声明一个值,然后在Console.WriteLine中使用该值来停止它,只需使用num的结束值 请参阅此以获得更清晰的解释。
执行查询时,数字==3 这是因为第一个foreach循环已经执行,最后一次分配给number的是infact 3 必要时延迟执行LINQ查询,例如在调用ToList时 这不是一个奇怪的结果,这就是它的本意
顺便说一句,在C 5.0 VS2012+编译器中,此行为已被修改为您期望的行为。linq表达式仅在需要其结果时才执行 所以 将在需要结果值时执行。但是,如果希望立即计算表达式,则需要从表达式中获取结果并创建一个对象 像 如果您想查看正确的流,那么在numbers2…中的from行上设置一个断点。。。。看看它什么时候被击中
希望能有所帮助……我得到的结果是123@Teejay顺便说一句,在C 5.0 VS2012+编译器中,此行为已修改为您所期望的。看起来这在C5中是固定的。0@weston好吧,它似乎只在C5中固定,所以在此之前你可以看到这种情况发生。@hjgraca我已经尝试了3.5、4和4.5,正如你所期望的1,2,3,1,2,3VS2010它按你所说的做,VS2012它按1,2,3,1,2,3做。所以与C版本无关,但与编译器有关。你每天都会学到一些新东西。是的,这正是我不明白的,为什么在执行查询的最后,它只返回{3,3,3}而不是{1,2,3}?因为,在最后,数字=3。因此,其中s==number的查询只在3上匹配。声明查询时,不会烘焙number的当前值。相反:每次执行查询时,它都会检查number的当前值。如果我执行list.Addresult.ToList,则您完全正确;看起来查询已经执行,结果还可以。但这绝对是一种奇怪的行为…@hjgraca你认为这很奇怪,因为你可能不习惯Linq的延迟执行特性。换句话说,linq查询在必要时才会执行。酷,在C5.0中它似乎是固定的。谢谢你看我对@user2025312关于固定词的回答的评论。我会说“修改”而不是“固定”。他们认为这可能会误导一些程序员,但我认为旧的行为是他们的本意,也可以为代码添加一些强大的工具。@Teejay:旧的行为的存在是因为C 1.0编译器的设计决定,将循环变量的声明置于循环之外。当时,没有lambdas或LINQ,因此也没有什么不同。即使是C开发人员自己也普遍认为这是一个错误,例如…@Heinzi是的,我很了解这篇博文。如果你读了它,你可以读到[…]有一些很好的理由不做这个改变[…],其中有4个理由,所以我的观点可能不是那么愚蠢。@Heinzi这是我最喜欢的:它会使foreach语义与for语义不一致
list.Add(result);
list.Add(result.ToList());
var result = from s in numbers2
where s == number
select s;
var result = (from s in numbers2
where s == number
select s).ToList();