Nzall
Nzall

Reputation: 3555

Why is my original hashset changed when I change a copy of it and how can I avoid it?

The intent of the below code is that it updates what's in my database to match what the user selected in my frontend. The proper Guids are in the Session variable, and _alreadyLinkedContacts contains the users that are already in the database.

    protected void btnAssignContacts_OnClick(object sender, EventArgs e)
    {
        btnAssignContacts.Enabled = false;
        //Venn diagram:

        //(Only in session --> add(both in session and Database -> keep) Only in database --> remove )

        HashSet<Guid> contactsInSession = (HashSet<Guid>)Session[SelectedContactsSessionVar];
        HashSet<Guid> contactsInDatabase = _alreadyLinkedContacts;
        //Everything that's in the session should go in the database;
        HashSet<Guid> contactsToAdd = contactsInSession;
        //Base the set to remove on that in the database.
        HashSet<Guid> contactsToRemove = contactsInDatabase;

        // We don't need to add those that are in the database already;
        contactsToAdd.RemoveWhere(contactsInDatabase.Contains);
        MarketingDirector.AddContactsToMarketingList(contactsToAdd.ToList(), _marketinglist.Id);

        // Those that are currently in the session don't need to be removed from the database, all the others do.
        contactsToRemove.RemoveWhere(contactsInSession.Contains);
        MarketingDirector.RemoveContactsFromMarketingList(contactsToRemove.ToList(), _marketinglist.Id);
        btnAssignContacts.Text = "Contacts assigned";
    }

After contactsToAdd has been filtered, contactsInSession has been changed as well, excluding the same guids as are in my system. Because of this, it doesn't remove anything from contactsToRemove and anything that already was in my database is removed, instead of just the stuff that is not in the session.

Why does this happen and how can I avoid it?

Upvotes: 0

Views: 734

Answers (2)

PhillipH
PhillipH

Reputation: 6222

You are making contactsToRemove and contactsInSession point to the same HashSet. Why wouldn't you expect contactsToRemove.RemoveWhere() to affect the contactsInSession HashSet ? I think you are missing a step which copies the data from one hashset to another, in your code you are always copying the reference not the content of the hashset.

Almost certainly these two lines

    //Everything that's in the session should go in the database;
    HashSet<Guid> contactsToAdd = contactsInSession;
    //Base the set to remove on that in the database.
    HashSet<Guid> contactsToRemove = contactsInDatabase;

Are incorrect ; they should copy the data from the source hashset not copy the reference pointer to that hashset. By doing reference copying you are simply declaring two variables which point to the same hashset - any changes made via either contactsToAdd OR contactsInSession will affect the same hashset.

Upvotes: 1

Coding Flow
Coding Flow

Reputation: 21881

As you seem to say in your comments when you do the following:

HashSet<Guid> contactsToAdd = contactsInSession;

You are assigning a second variable to reference the same HashSet as the original. If you do the folowing you will create a new HashSet that is a copy of the original.

HashSet<Guid> contactsToAdd = new HashSet<Guid>(contactsInSession);

You might want to do the same for all your assignments where you want a copy of the HashSet.

Upvotes: 3

Related Questions