您能否解释一下为什么执行以下代码后Selected
属性未更新为true
?
使用的ListItem
类型来自System.Web.UI.WebControls
命名空间,是一个类(不是结构体)。我相信FirstOrDefault
函数返回对我可以更新和传递的实例的引用在items
枚举中。
// produce list items out of the communities
IEnumerable<ListItem> items = communities.Select(community => new ListItem(community.Name, community.Id.ToString()));
// mark the right list item as selected, if needed
if (platform.CommunityId > 0)
{
string strCommunityId = platform.CommunityId.ToString();
ListItem selectedItem = items.FirstOrDefault(item => item.Value == strCommunityId);
if (selectedItem != null) selectedItem.Selected = true;
}
// now items do not store any updated item!
这是因为每次调用foreach
时都会执行枚举器,从而创建新项而不是返回包含我更新的项的集合吗?
答案 0 :(得分:17)
问题是IEnumerable
不可重复。您每次枚举时都会执行投影(community => new ListItem
) - 因此每次都是新的ListItem
。 Select
是一个非缓冲的延迟投影。
您可以通过简单添加.ToList()
来修复所有内容,以强制将数据放入单个列表中;
var items = communities.Select(
community => new ListItem(community.Name, community.Id.ToString())
).ToList();
既然数据在列表中,您可以循环遍历列表 - 它始终是相同的项目,并且将保留更改。
答案 1 :(得分:5)
会发生这种情况,因为您使用的是Select
:
IEnumerable<ListItem> items = communities
.Select(community => new ListItem(community.Name, community.Id.ToString()));
每次遍历项目时都会创建新对象。
答案 2 :(得分:5)
你的问题是那个
IEnumerable<ListItem> items = communities
.Select(community => new ListItem(community.Name, community.Id.ToString()));
创建一个IEnumerable 懒惰评估 - 也就是说,每次枚举时,重新枚举原始communities
序列,并Select
按顺序重新执行每个项目的投影。
如果您在最后粘贴.ToList()
,请将该行更改为:
IEnumerable<ListItem> items = communities
.Select(community => new ListItem(community.Name, community.Id.ToString()))
.ToList();
您将观察到不同的结果。虽然它仍然是IEnumerable
,但它将不再是一个懒惰的评估版本,并且您在其中所做的更改将在以后的迭代中通过相同的IEnumerable
进行观察。
答案 3 :(得分:3)
我认为Marc Gravell的答案是正确的,但你可以避免这种混乱,并在一行中做到(可能导致另一种混乱)。 ;)
// produce list items out of the communities
IEnumerable<ListItem> items = communities.Select(community =>
new ListItem(community.Name, community.Id.ToString())
{
Selected = community.Id == platform.CommunityId
});