Я не понимаю, как обновить объект, на который есть ссылка в коллекции. Моя коллекция:
List<Person> people
Я хочу обновить элемент в людях с помощью обновленного объекта.
var existingPepe = people.Where(a => a.id ==someId).FirstOrDefault();
// on examintion existingperson.Age = 101;
Person person = new Person();
person.Age = 65;
Теперь обновите существующий Pepe с помощью человека;
existingPepe = person;
Но это не обновляет Person в коллекции - почему возраст объектов до 101?
existingperson — указатель на объект. В коллекции people также есть указатель на тот же объект. existingperson = person; заменил указатель для existingperson на другой объект но список people по-прежнему содержит ссылку на «исходный» объект.
Вы должны понимать, что такое ссылка на объект. Здесь вы указываете переменную на существующий объект, а затем заменяете эту ссылку ссылкой на новый объект. Список по-прежнему указывает на исходный объект, вы просто указываете переменную existingPerson на новый объект.
Ах, я вижу - как мне обновить существующий Pepe?
Now update existingPepe with person Нет, вы просто устанавливаете existingPepe ссылку на тот же объект, что и новый person«Как мне обновить существующий Пепе»: existingPepe.Age = 65; или вы можете сделать это в одной строке: people.Single(a => a.id ==someId).Age = 65; при условии, что будет только одно совпадение.
PaulStanley, ваш принятый ответ неверен, и у него будет побочный эффект. Пожалуйста, пересмотрите ответ @Igor вместо этого





Позвольте мне помочь вам здесь. Чтобы обновить List, нужно получить ссылку на правильное место в списке и обновить его. Индекс — это один из способов сделать это со списком.
var indx = people.FindIndex(a => a.id == someId);
if (indx >= 0) {
//people[indx].Age = 65; // in case you want to update the found record
Person person = new Person();
person.Age = 65;
people[indx] = person; // set a new Person in the existing slot of the list
}
Здесь я использую функцию List<T>.FindIndex, чтобы найти соответствующую запись, затем использую этот индекс для обновления существующей записи, а затем заменяю этот слот новым человеком.
Обновлять
I want to update an item in people with an updated object
Чтобы ответить на кучу комментариев здесь. Я не могу предположить, что Person является class или struct, и я не могу сказать, является ли это immutable class. Поэтому я не могу предположить, что поле может обновляться. Кроме того, код в вопросе явно оставляет неясным, хочет ли OP обновить существующий объект или установить новый объект в этом слоте. Оба являются очень распространенным поведением, и, следовательно, мой образец демонстрирует оба, поэтому ОП может решить, какой из них работает для них.
основан ли FindIndex 0?
Будет ли это ошибкой, если это будет первый элемент? О, я верю, что он вернет -1, если его не существует.
Это не верно. Почему вы создаете нового человека, а не обновляете существующего?
@Vikhram, вы здесь НЕ обновляете объект. Вы создаете новый. Если вы пытались удалить и заменить, вы не удаляете старый объект или не копируете значения старых объектов.
@Вихрам Точно. В примере создается новый экземпляр Person. Создавая экземпляр нового объекта Person, он, по сути, очищает любые другие поля, которые могут быть установлены из существующего объекта Pepe. Но я не уверен, почему индекс имеет значение здесь, если это список.
@Vikhram, вы отвечаете, НЕ обновляет объект, он создает новый.
@Vikhram, например, вы создаете нового человека в возрасте 65 лет. Но у старого человека имя Фред. теперь у нового человека нет имени Фред.
@Vikhram, Нет, 1. Это не показывает, как обновить запись. Он показывает, как заменить запись, которая НЕ будет копировать существующие значения. 2. В своем ответе вы делаете предположение, что people является ссылкой непосредственно на коллекцию, и что, если вы добавите обратно в этот список, он будет добавлен обратно в исходную коллекцию. Так что этот ответ уже неверен в двух отношениях. Если вы прочитаете вопрос дальше, мне совершенно ясно, что ОП неясен в отношении ссылочных типов, и они предполагают, что присвоение ссылки existingPepe = person обновит существующий Пепе.
Если вы посмотрите на ответ @Igors, он обходит заблуждения ОП и правильно отвечает на вопрос.
Вы не можете утверждать, что тип может быть неизменяемым, когда вы мутируете его в своем коде. Если бы он был неизменным, ваш код не работал бы. Этот тип вообще не имеет смысла как структура. Если это один, он изменчив, не представляет единственное значение, вряд ли будет/останется маленьким и т. д. Его следует изменить, чтобы он был классом, если это еще не так. Все это говорит о том, что есть причины для изменения ссылочного объекта, а не для изменения существующего. Все сводится к желаемому поведению, и мы не можем знать это из показанного кода. Вопрос также неоднозначен относительно того, о чем он на самом деле просит.
Переменная existingPepe содержит ссылку на объект, выбранный из списка. Параметр existingPepe = person; изменяет ссылку, чтобы она указывала на ваш новый объект Person. Переменные existingPepe и person теперь указывают/ссылаются на один и тот же объект. Ссылка исходного списка на существующего человека не затрагивается последующими операциями. Вам нужно будет обновить ссылку списка на существующий объект, чтобы указать на ваш новый объект, установив его index.
если ваша цель - обновить возраст человека в этой коллекции, вы можете сделать это с помощью linq, подобного этому
people.Where(a => a.id == someId).Select(a => a.Age = 65; return a).ToList();
Я бы предложил это, но это не синтаксис: people.Where(a => a.id == someId).Select(a => {a.Age = 65; return a;}).ToList();
Если вы хотите заменить сам объект в коллекции, выполните удаление/добавление:
if (people.Remove(people.Where(a => a.id ==someId).FirstOrDefault()))
people.Add(new Person {Age=65});
Если вы хотите обновить человека. Затем просто измените тот, который вы нашли в памяти
var existingPepe = people.Where(a => a.id ==someId).FirstOrDefault();
existingPepe.Age = 65;
Вы по-старому создавали нового человека, не добавляя его в коллекцию.
"How should I update the existingPepe"
Нет необходимости создавать новый экземпляр Person, вы можете обновить свойство Age непосредственно в существующем найденном экземпляре. Это мутирует сам фактический экземпляр. Это также означает, что нет необходимости менять предмет в List<Person>.
// note that SingleOrDefault will throw an exception if there is more than one match
var foundPerson = people.SingleOrDefault(a => a.id ==someId);
if (foundPerson != null)
foundPerson.Age = 65;
// else person with that id does not exist in the list
Если вы хотите, чтобы при отсутствии совпадений было создано исключение, используйте вместо этого Single.
var foundPerson = people.Single(a => a.id ==someId);
foundPerson.Age = 65;
Какова ваша цель здесь?
existingPepe.Age = 65;обновит объект в списке. Создание нового объекта и изменение переменнойexistingPepeдля ссылки на него не изменит объект, на который ссылается список.