Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# copied property loses reference when referenced object is removed from list

Example

Have a look at the following code:

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();
}

In this example the property CompanyInfoOrganisation (simply a get; set; property) is copied when an organisation is considered a duplicate. This all works as expected, duplicates are nicely deduplicated.

Also this is true inside this message:
_organisations.First(o => o.ExistsInBoth).CompanyInfoOrganisation != null;

Problem

Now I bind the _organisations list to a listbox

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

and later on get the selected value:

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

If I try to read the CompanyInfoOrganisation property I always get null while I know the property was set.

Question

What is happening here? How come the property reference is destroyed? How can I prevent this from happening?

like image 961
Corné Hogerheijde Avatar asked Jan 27 '26 14:01

Corné Hogerheijde


1 Answers

The reference you're using only has immediate scope and as soon as the query ends it exits scope and your reference disappears. So when you bind later, the reference is exactly right -- 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);
    }
});

Because you're using a class, you need to perform a deep MemberwiseClone on it to get a NEW copy of the object:

o.CompanyInfoOrganisation = (YourInfoType)duplicate.CompanyInfoOrganisation.MemberwiseClone();
like image 59
Joel Etherton Avatar answered Jan 29 '26 02:01

Joel Etherton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!