2015-04-16 32 views
4

您能否向我解释为什么执行以下代码后Selected属性未更新为true为什么IEnumerable会丢失更新的数据?

使用的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被调用时执行,从而创造新的项目,而不是返回包含我更新了项目的设定?

回答

16

问题是IEnumerable不可重复。您每次执行投影(community => new ListItem - 因此每次都是新的ListItemSelect是一个非缓冲的延迟投影。

您可以通过简单地添加.ToList()来强制将数据强制到单个列表中;现在

var items = communities.Select(
    community => new ListItem(community.Name, community.Id.ToString()) 
).ToList(); 

数据是在列表中,您可以循环在列表任意次数 - 这将永远是相同的项目,并更改将被保留。

3

它发生,因为你用Select

IEnumerable<ListItem> items = communities.Select(community => new ListItem(community.Name, community.Id.ToString())); 

它创建每次通过项目迭代时间的新对象。

4

您的问题是

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

我认为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 
    }); 
相关问题