Mehdi Souregi
Mehdi Souregi

Reputation: 3265

Update an item in the list not working

I tried to simplify my problem with this example:

List<User> userList = new List<User>()
                {
                    new User {IdUser = 1, Login = "Frank" },
                    new User {IdUser = 2, Login = "Pat" },
                    new User {IdUser = 3, Login = "Max" },
                    new User {IdUser = 4, Login = "Paul" },
                    new User {IdUser = 5, Login = "John" }
                };

User newUser = new User()
    {
         IdUser = 3,
         Login = "Chris"
    };

var userToUpdate = userList.FirstOrDefault(r => r.IdUser == 3);
userToUpdate = newUser;

why userList does not contain the value Login = "Chris" by the end of this program? How is it possible to update an item within a list?

PS1: I don't want to update the Login value, I want to update the User Object

PS2: It says in this link that FirstOrDefault selects an item in a collection, but does not "detatch" or "clone" it. I.e. it is the same instance. So if you modify a property you modify the original instance.

I am confused!

Upvotes: 10

Views: 8755

Answers (6)

Fabjan
Fabjan

Reputation: 13676

Think of it this way :

Collection is a grid of cells let's say post office boxes, and somewhere in one of these boxes it contains object1. You're uncertain in which box it is so by invoking .FirstOrDefault you ask the 'other guy' to go and find the cell for you. You describe what this object looks like and after he's finished he provides you with information about where object is stored in what box. (reference to pointer that points to object location in physical memory).

Let's say that our userToUpdate is a page number 1 in your notebook where you wrote down this information he told you. Then you go to the next page (page2), it contains record about some other object (newUser).

What you do next ? You go back to the previous page and substitute what's written there (on page1) with information from page2 that contains a record: "object is in the dinning room".

Then you tear off the page and give it to 'the other guy' saying "Yo! I need some changes to object1, here's the paper with address, it'll help you to find it, go and change it".

Guess what will happen next ? He'll go to the dinning room.

Upvotes: 1

Roman
Roman

Reputation: 12201

Doing this:

var userToUpdate = userList.FirstOrDefault(r => r.IdUser == 3);

you get copy of reference that points to needed user. So, there are two different references pointing to this user: userToUpdate and reference inside userList.

When you assign newUser to userToUpdate you have one reference from list still pointing to the old user and you get reference userToUpdate pointing to newUser.

To update user you should do something like this:

var index = userList.FindIndex(r => r.IdUser == 3);

if (index != -1)
{
    userList[index].Id = newUser.Id,
    //set all other properties from newUser
}

OR

simpler way:

var index = userList.FindIndex(r => r.IdUser == 3);

if (index != -1)
{
    userList[index] = newUser;        
}

Upvotes: 13

ad1Dima
ad1Dima

Reputation: 3197

But you aren't modifying property you are modifying variable value.

Try to add:

var ind = userList.IndexOf(userToUpdate);
userList[ind] = newUser;

Upvotes: 2

Theo
Theo

Reputation: 885

What you are describing is replacing an instance of an object in the list with a different object instance, rather than updating the instance. You can accomplish that with something like this:

List<User> userList = new List<User>()
    {
        new User {IdUser = 1, Login = "Frank" },
        new User {IdUser = 2, Login = "Pat" },
        new User {IdUser = 3, Login = "Max" },
        new User {IdUser = 4, Login = "Paul" },
        new User {IdUser = 5, Login = "John" }
    };

User newUser = new User()
{
    IdUser = 3,
    Login = "Chris"
};

var foundUser = userList.FirstOrDefault(item => item.IdUser == newUser.IdUser);
if(foundUser != null)
    userList.Remove(foundUser)
userList.Add(newUser);

Upvotes: 0

rory.ap
rory.ap

Reputation: 35318

The reason for this has to do with the way objects are stored and referenced in memory. When you are adding your User objects initially to the collection, the collection is storing references to each of those objects.

Then on this line:

var userToUpdate = userList.FirstOrDefault(r => r.IdUser == 3);

You are creating a second reference to one of the objects which is in the list from above. However, you then overwrite that reference by assigning newUser to it: userToUpdate = newUser;. The reference to the original user whose IdUser value is 3 still remains intact in the list. You need to replace that element in the list with the new element:

int toReplaceIndex = userList.FindIndex(r => r.IdUser == 3);

if (toReplaceIndex == -1)
{
    userList[toReplaceIndex] = newUser;
}
else
{
    // do whatever you want when the user ID being replaced doesn't exist.
}

Upvotes: 4

MistyK
MistyK

Reputation: 6232

Because here

var userToUpdate = userList.FirstOrDefault(r => r.IdUser == 3);

you get the copy of a reference not the actual reference.

Upvotes: 0

Related Questions