Reputation: 3265
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
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
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
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
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
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
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