IEnumerable 中的项目在 foreach 内部发生了更改,但更改未保存到集合中
Item from IEnumerable changed inside foreach, but change not saved to collection
我今天遇到了一个有趣的问题,这是一个复现:
class TestListAndEnumerable
{
public static void Test()
{
bool b1 = GetBool1(); // returns false
bool b2 = GetBool2(); // returns true
}
private static bool GetBool1()
{
IEnumerable<BoolContainer> list = new List<bool> { false }.Select(x => new BoolContainer { Value = x });
foreach (BoolContainer item in list)
{
item.Value = true;
}
return list.Select(x => x.Value).First();
}
private static bool GetBool2()
{
List<BoolContainer> list = new List<bool> { false }.Select(x => new BoolContainer { Value = x }).ToList();
foreach (BoolContainer item in list)
{
item.Value = true;
}
return list.Select(x => x.Value).First();
}
private class BoolContainer
{
public bool Value { get; set; }
}
}
在 GetBool1()
中,更改 item
的值对 list
变量没有影响。
GetBool2()
按预期工作。
有人知道为什么会这样吗?
[关于重复标签]
我认为它与 this question 中的问题基本相同,但这里的问题更加简洁和切题,所以我将保留它。
这是LINQ惰性求值的问题。每次在 GetBool1()
中迭代 list
时,您都会创建一个新的值序列。更改其中一个对象中的 Value
属性 不会改变任何其他内容。
将其与 GetBool2()
进行比较,您会调用 ToList()
,这意味着您正在创建一个包含一系列对象的 List<T>
。现在每次您遍历该列表,您将获得对相同对象的引用...因此,如果您修改其中一个对象中的值,您将在下次看到。
如果您将 Select argument
更改为
x => { Console.WriteLine("Selecting!"); return 新的 BoolContainer { 值 = x } };
...然后添加适当的额外 Console.WriteLine
调用,以便您可以看到它何时发生,您会看到在调用 [=14] 之后从未在 GetBool2()
中调用委托=],但在 GetBool1()
中,每次迭代序列时都会调用它。
我今天遇到了一个有趣的问题,这是一个复现:
class TestListAndEnumerable
{
public static void Test()
{
bool b1 = GetBool1(); // returns false
bool b2 = GetBool2(); // returns true
}
private static bool GetBool1()
{
IEnumerable<BoolContainer> list = new List<bool> { false }.Select(x => new BoolContainer { Value = x });
foreach (BoolContainer item in list)
{
item.Value = true;
}
return list.Select(x => x.Value).First();
}
private static bool GetBool2()
{
List<BoolContainer> list = new List<bool> { false }.Select(x => new BoolContainer { Value = x }).ToList();
foreach (BoolContainer item in list)
{
item.Value = true;
}
return list.Select(x => x.Value).First();
}
private class BoolContainer
{
public bool Value { get; set; }
}
}
在 GetBool1()
中,更改 item
的值对 list
变量没有影响。
GetBool2()
按预期工作。
有人知道为什么会这样吗?
[关于重复标签]
我认为它与 this question 中的问题基本相同,但这里的问题更加简洁和切题,所以我将保留它。
这是LINQ惰性求值的问题。每次在 GetBool1()
中迭代 list
时,您都会创建一个新的值序列。更改其中一个对象中的 Value
属性 不会改变任何其他内容。
将其与 GetBool2()
进行比较,您会调用 ToList()
,这意味着您正在创建一个包含一系列对象的 List<T>
。现在每次您遍历该列表,您将获得对相同对象的引用...因此,如果您修改其中一个对象中的值,您将在下次看到。
如果您将 Select argument
更改为
x => { Console.WriteLine("Selecting!"); return 新的 BoolContainer { 值 = x } };
...然后添加适当的额外 Console.WriteLine
调用,以便您可以看到它何时发生,您会看到在调用 [=14] 之后从未在 GetBool2()
中调用委托=],但在 GetBool1()
中,每次迭代序列时都会调用它。