更新 IEnumerable 中的项目
Updating items in an IEnumerable
我有这个代码:
class Foo
{
public string A { get; set; }
}
class Program
{
static void Main(string[] args)
{
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x });
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
}
}
打印:
foo
foo
设置 item.A = "bar"
时究竟发生了什么?
在第一个 foreach 循环完成后,list
var 是否真的包含相同的两个 Foo
对象并将 "bar"
作为新字符串?
如果是这样,您如何访问这些新值?
我知道当第二个 foreach 循环 运行s 时,它正在枚举字符串集合,这就是为什么你得到两个 "foo"
的打印输出,但我只是对当 item.A = "bar"
为 运行 时会发生什么,如果您永远无法访问该新值,为什么编译器允许您修改它?
问题是您没有调用 ToList
方法来实现您的 LINQ 查询。当您按如下方式调用 ToList
时:
var list = strings.Select(x => new Foo { A = x })
.ToList();
将创建 Foo
个对象的内存集合,其 属性 值 A
的值为 x
。本质上,将创建两个 Foo
类型的新对象,A
的值为 "foo"。然后你可以遍历这个列表并修改 属性 值。
请看这个fiddle
你是对的,如果不会被改变,那么为什么编译器允许。但如果您想在这种情况下打印而不更新实际项目,上面的代码会有所帮助。
有一件事你应该知道,你不能修改 IEnumerable 对象的项目。
你必须使用 List();
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x }).ToList();
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
这里发生的事情是您正在创建一个可枚举的 list
,您正在枚举多次。
每次枚举list
,枚举处理strings
列表的元素,为每个元素调用new Foo { A = x }
创建结果序列的元素。
这意味着第一个 foreach
枚举创建的 Foo
对象与第二个 foreach
枚举创建的对象不同。为每个枚举创建新的。
这就是 Resharper 警告 "possible multiple enumeration" 的原因。
为避免这种情况,您可以使用 var list = strings.Select(x => new Foo { A = x }).ToList();
仅枚举序列一次并将结果存储在实际的 List<T>
.
中
我有这个代码:
class Foo
{
public string A { get; set; }
}
class Program
{
static void Main(string[] args)
{
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x });
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
}
}
打印:
foo
foo
设置 item.A = "bar"
时究竟发生了什么?
在第一个 foreach 循环完成后,list
var 是否真的包含相同的两个 Foo
对象并将 "bar"
作为新字符串?
如果是这样,您如何访问这些新值?
我知道当第二个 foreach 循环 运行s 时,它正在枚举字符串集合,这就是为什么你得到两个 "foo"
的打印输出,但我只是对当 item.A = "bar"
为 运行 时会发生什么,如果您永远无法访问该新值,为什么编译器允许您修改它?
问题是您没有调用 ToList
方法来实现您的 LINQ 查询。当您按如下方式调用 ToList
时:
var list = strings.Select(x => new Foo { A = x })
.ToList();
将创建 Foo
个对象的内存集合,其 属性 值 A
的值为 x
。本质上,将创建两个 Foo
类型的新对象,A
的值为 "foo"。然后你可以遍历这个列表并修改 属性 值。
请看这个fiddle
你是对的,如果不会被改变,那么为什么编译器允许。但如果您想在这种情况下打印而不更新实际项目,上面的代码会有所帮助。
有一件事你应该知道,你不能修改 IEnumerable 对象的项目。 你必须使用 List();
var strings = new List<string> { "foo", "foo" };
var list = strings.Select(x => new Foo { A = x }).ToList();
foreach (var item in list)
{
item.A = "bar";
}
foreach (var item in list)
{
Console.WriteLine(item.A);
}
这里发生的事情是您正在创建一个可枚举的 list
,您正在枚举多次。
每次枚举list
,枚举处理strings
列表的元素,为每个元素调用new Foo { A = x }
创建结果序列的元素。
这意味着第一个 foreach
枚举创建的 Foo
对象与第二个 foreach
枚举创建的对象不同。为每个枚举创建新的。
这就是 Resharper 警告 "possible multiple enumeration" 的原因。
为避免这种情况,您可以使用 var list = strings.Select(x => new Foo { A = x }).ToList();
仅枚举序列一次并将结果存储在实际的 List<T>
.