循环(IEnumerable)结果和更新,但没有更新?

时间:2011-12-01 22:38:24

标签: c# linq foreach

我正在通过父记录(“欧洲”)进行循环,并使用其子记录更新名为“ childPublication ”的<Ienumerable>字段。但是循环和赋值后 childPublication 为空?

这是我的代码:

foreach (var e in europe)
{
    string child = e.HasChild ?? "";
    if (child.Contains("True"))
    {
        IEnumerable<Publication> eChildrens = children.OfType<Publication>()
                                                .Where(ep => ep.ParentID.Equals(e.PublicationId));

        if (eChildrens.Count() > 0)
        {
            e.ChildPublication = eChildrens;
        }
    }
}              

member.EuropeMiddleEastAfricaPublication = europe;

public class Publication
{
    public int PublicationId { get; set; }
    public int ContentTypeId { get; set; }
    public string PublicationName { get; set; }
    public string PublicationFullName { get; set; }
    public string ShortDescription { get; set; }
    public string LongDescription { get; set; }
    public string URL { get; set; }
    public string CountryId { get; set; }
    public string LanguageId { get; set; }
    public string Active { get; set; }
    public string Subscription { get; set; }
    public string ClientOnly { get; set; }
    public string PrintVersion { get; set; }
    public string EmailVersion { get; set; }
    public string RegisteredforPrint { get; set; }
    public string RegisteredforEmail { get; set; }
    public int ParentID { get; set; }
    public string HasChild { get; set; }
    public IEnumerable<Publication> ChildPublication { get; set; }
}

4 个答案:

答案 0 :(得分:1)

首先,你有eChildren = children,所以我假设孩子在某个地方被传递了?

我可能会编写类似的代码:

foreach (var e in europe) 
{ 
  // .Net 4.0 use: string.IsNullOrWhiteSpace()
  if (!string.IsNullOrEmpty(e.HadChild)
         // I prefer IndexOf which allows Culture and IgnoreCase 
      && e.HasChild.IndexOf("True", StringComparison.CurrentCultureIgnoreCase))
  { 
    IEnumerable<Publication> eChildrens = 
      children.OfType<Publication>()
              .Where(ep => ep.ParentID.Equals(e.PublicationId))
              .ToList();  //Force the IEnumeration to Enumerate.

    if (eChildrens.Count() > 0) 
    { 
      e.ChildPublication = eChildrens; 
    } 
  } 
}    

答案 1 :(得分:0)

您应该调试程序并验证您实际进入if并设置属性。如果你不是,那么它绝对是空的。但请注意,通过关闭循环变量,您无论如何都在做一些危险的事情。

IEnumerable<Publication> eChildrens = 
  children.OfType<Publication>().Where(ep =>  
                                         ep.ParentID.Equals(e.PublicationId)); 

if (eChildrens.Count() > 0) 
{ 
     e.ChildPublication = eChildrens; 
} 

eChildrens是一个延迟评估的查询,它捕获循环变量e。当你超出查询范围并尝试使用结果时,除非你有奇怪的期望,否则你的代码不会按照你想要的去做。在闭包中,捕获的是变量,因此当您离开循环时,您的查询将始终查看相同的 var e。你将会有很多对象查看错误的ChildPublication序列。

要避免此问题,请在循环内创建一个本地临时变量并关闭该

var temp = e; // local temporary variable, used below
IEnumerable<Publication> eChildrens = 
  children.OfType<Publication>().Where(ep =>  
                                         ep.ParentID.Equals(temp.PublicationId)); 

if (eChildrens.Count() > 0) 
{ 
  e.ChildPublication = eChildrens; 
} 

或者通过调用ToList();

等方法来强制评估查询
IEnumerable<Publication> eChildrens = 
  children.OfType<Publication>().Where(ep =>  
                                         ep.ParentID.Equals(e.PublicationId)).ToList(); 

if (eChildrens.Count() > 0) 
{ 
  e.ChildPublication = eChildrens; 
} 

有关此主题的更多信息,请阅读Eric Lippert的blog entry

答案 2 :(得分:0)

这是问题所在。 IEnumerable用户是针对您的数据源运行的迭代器。迭代器返回一个新对象,而不是对原始对象的引用。

因此,您要对原始数据的副本进行更改,而不是对实际数据进行更改。如果要修改原始数据,则需要传递对它的引用并使用该引用。

答案 3 :(得分:-1)

您是否尝试过使用List<Publication>IEnumerable<Publication>。对于简单的收集处理,我总是有更多的成功。 IEnumerable经常需要定义一个Enumerator,这是一个更多的开销。