当从列表中删除引用的对象时,c#复制的属性将丢失引用

时间:2012-07-11 11:41:38

标签: c# linq properties reference

示例

查看以下代码:

private void DeDuplicateOrganisations()
{
     var profileOrgs = _organisations.Where(o => o.ExistsInProfile).ToList();
     var kvkOrgs = _organisations.Where(o => !o.ExistsInProfile).ToList();

     profileOrgs.ForEach(o =>
         {
             var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
             if (duplicate != null)
             {
                  o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
                  o.ExistsInBoth = true;
                  kvkOrgs.Remove(duplicate);
              }
           });

      _organisations = profileOrgs.Concat(kvkOrgs).OrderBy(o => o.Title).ToList();
}

在此示例中,当组织被视为重复时,将复制属性CompanyInfoOrganisation(只是get; set;属性)。这一切都按预期工作,复制品很好地重复数据删除。

在此消息中也是如此:
_organisations.First(o => o.ExistsInBoth).CompanyInfoOrganisation != null;

问题

现在我将_organisations列表绑定到列表框

lbxCompanies.DataSource = null;
lbxCompanies.DataSource = _organisations;
lbxCompanies.DisplayMember = "Title";
lbxCompanies.SelectedIndex = -1;

以及稍后获取所选值:

 var org = lbxCompanies.SelectedValue as Organisation;
 gbxCompanyInfo.Visible = org != null;
 if (gbxCompanyInfo.Visible)
    if (org.CompanyInfoOrganisation != null)
          // NEVER GETS HERE (but gbxComanpyInfo is visible)

如果我尝试读取CompanyInfoOrganisation属性,我知道属性设置时总是为null。

问题

这里发生了什么?财产参考怎么被破坏?我怎样才能防止这种情况发生?

4 个答案:

答案 0 :(得分:4)

您使用的引用只有立即范围,一旦查询结束,它就会退出范围,您的引用就会消失。因此,当您稍后绑定时,引用完全正确 - null。

profileOrgs.ForEach(o =>
{
    // Right here -- var duplicate has scope ONLY within your query. 
    // As soon as the query is executed it leaves scope and the reference
    // pointer will be null
    var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
    if (duplicate != null)
    {
        o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
        o.ExistsInBoth = true;
        kvkOrgs.Remove(duplicate);
    }
});

因为您正在使用某个类,所以需要在其上执行深MemberwiseClone以获取该对象的新副本:

o.CompanyInfoOrganisation = (YourInfoType)duplicate.CompanyInfoOrganisation.MemberwiseClone();

答案 1 :(得分:0)

加载数据时,请将CompanyInfoOrganisation属性与根实体一起加载;这样它就会被加载到内存中。如果使用LINQ to SQL,则通过DataLoadOptions加载,并将其传递给上下文。如果使用Entity Framework,则在LINQ查询中使用Include方法。

答案 2 :(得分:0)

它可能与在lambda中捕获变量有关。尝试将.ForEach替换为常规foreach()。 或者,一开始就是一式两份的CompanyInfoOrganisation为空。

答案 3 :(得分:0)

问题是我使用string.Join()来显示值,并且第一个连接值是null(这真的很烦人),导致一个空字符串,让我觉得该属性为null。然而事实证明该属性不是null,但对所需对象有完全有效的引用。稍微使用调试器会让我节省一个小时......

抱歉!