我在linq和集合之间的交互中发现了行为,我无法理解。
我被教导,通过此集合枚举期间更改集合会导致InvalidOperationException。
但这有点复杂。
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public void Main()
{
Program.Try(Program.HandleArray_Where, "array.where");
Program.Try(Program.HandleArray_Where_OrderBy, "array.where.orderby");
Program.Try(Program.HandleList_Where, "list.where");
Program.Try(Program.HandleList_Where_OrderBy, "list.where.orderby");
}
private static void Try(Action action, string text)
{
Console.WriteLine(text);
try
{
action.Invoke();
}
catch (InvalidOperationException)
{
Console.WriteLine("Invalid operation");
}
Console.WriteLine();
Console.WriteLine();
}
private static void HandleArray_Where()
{
IList<int> arr = new[] { 1, 2, 3, 4, 5 };
var enumerable = arr.Where(item => item > 2);
foreach (var item in enumerable)
{
arr[3] = 0;
Console.WriteLine(item);
}
}
private static void HandleArray_Where_OrderBy()
{
IList<int> arr = new[] { 1, 2, 3, 4, 5 };
var orderedEnumerable = arr.Where(item => item > 2).OrderBy(asd => asd);
foreach (var item in orderedEnumerable)
{
arr[3] = 0;
Console.WriteLine(item);
}
}
private static void HandleList_Where()
{
IList<int> list = new List<int> { 1, 2, 3, 4, 5 };
var enumerable = list.Where(item => item > 2);
foreach (var item in enumerable)
{
list[3] = 0;
Console.WriteLine(item);
}
}
private static void HandleList_Where_OrderBy()
{
IList<int> list = new List<int> { 1, 2, 3, 4, 5 };
var orderedEnumerable = list.Where(item => item > 2).OrderBy(asd => asd);
foreach (var item in orderedEnumerable)
{
list[3] = 0;
Console.WriteLine(item);
}
}
}
有四个集合,我试图在枚举期间更改它们。我应该有四次InvalidOperationException,但我只有一次。
输出:
array.where
3
5
array.where.orderby
3
4
5
list.where
3
Invalid operation
list.where.orderby
3
4
5
所以,我可以解释这样的结果:
.OrderBy()
使用.Where()
的结果,使用新的集合,不会感觉到原始集合的变化,因为样本是在更改之前拍摄的。所以在块“array.where.orderby”和“list.where.orderby”中有三个数字。
但是我不理解“array.where”和“list.where”块的行为。为什么我可以在迭代期间更改int[]
并且无法更改List<int>
,尤其是如果它们都转换为IList<int>
?现在我认为这是与Liskov替换原则的差异:一个父类型有两种不同的行为,具体取决于变量的真实类型