Обновление объекта в коллекции C#

Я не понимаю, как обновить объект, на который есть ссылка в коллекции. Моя коллекция:

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?

Какова ваша цель здесь? existingPepe.Age = 65; обновит объект в списке. Создание нового объекта и изменение переменной existingPepe для ссылки на него не изменит объект, на который ссылается список.

Blorgbeard 29.03.2019 19:36
existingperson — указатель на объект. В коллекции people также есть указатель на тот же объект. existingperson = person; заменил указатель для existingperson на другой объект но список people по-прежнему содержит ссылку на «исходный» объект.
Igor 29.03.2019 19:36

Вы должны понимать, что такое ссылка на объект. Здесь вы указываете переменную на существующий объект, а затем заменяете эту ссылку ссылкой на новый объект. Список по-прежнему указывает на исходный объект, вы просто указываете переменную existingPerson на новый объект.

Charleh 29.03.2019 19:37

Ах, я вижу - как мне обновить существующий Pepe?

Paul Stanley 29.03.2019 19:38
Now update existingPepe with person Нет, вы просто устанавливаете existingPepe ссылку на тот же объект, что и новый person
Ňɏssa Pøngjǣrdenlarp 29.03.2019 19:39

«Как мне обновить существующий Пепе»: existingPepe.Age = 65; или вы можете сделать это в одной строке: people.Single(a => a.id ==someId).Age = 65; при условии, что будет только одно совпадение.

Igor 29.03.2019 19:39

PaulStanley, ваш принятый ответ неверен, и у него будет побочный эффект. Пожалуйста, пересмотрите ответ @Igor вместо этого

johnny 5 29.03.2019 20:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
1 519
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Позвольте мне помочь вам здесь. Чтобы обновить 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?

Paul Stanley 29.03.2019 19:43

Будет ли это ошибкой, если это будет первый элемент? О, я верю, что он вернет -1, если его не существует.

Paul Stanley 29.03.2019 19:46

Это не верно. Почему вы создаете нового человека, а не обновляете существующего?

johnny 5 29.03.2019 19:46

@Vikhram, вы здесь НЕ обновляете объект. Вы создаете новый. Если вы пытались удалить и заменить, вы не удаляете старый объект или не копируете значения старых объектов.

johnny 5 29.03.2019 19:52

@Вихрам Точно. В примере создается новый экземпляр Person. Создавая экземпляр нового объекта Person, он, по сути, очищает любые другие поля, которые могут быть установлены из существующего объекта Pepe. Но я не уверен, почему индекс имеет значение здесь, если это список.

alans 29.03.2019 19:52

@Vikhram, вы отвечаете, НЕ обновляет объект, он создает новый.

johnny 5 29.03.2019 19:53

@Vikhram, например, вы создаете нового человека в возрасте 65 лет. Но у старого человека имя Фред. теперь у нового человека нет имени Фред.

johnny 5 29.03.2019 19:55

@Vikhram, Нет, 1. Это не показывает, как обновить запись. Он показывает, как заменить запись, которая НЕ будет копировать существующие значения. 2. В своем ответе вы делаете предположение, что people является ссылкой непосредственно на коллекцию, и что, если вы добавите обратно в этот список, он будет добавлен обратно в исходную коллекцию. Так что этот ответ уже неверен в двух отношениях. Если вы прочитаете вопрос дальше, мне совершенно ясно, что ОП неясен в отношении ссылочных типов, и они предполагают, что присвоение ссылки existingPepe = person обновит существующий Пепе.

johnny 5 29.03.2019 20:05

Если вы посмотрите на ответ @Igors, он обходит заблуждения ОП и правильно отвечает на вопрос.

johnny 5 29.03.2019 20:08

Вы не можете утверждать, что тип может быть неизменяемым, когда вы мутируете его в своем коде. Если бы он был неизменным, ваш код не работал бы. Этот тип вообще не имеет смысла как структура. Если это один, он изменчив, не представляет единственное значение, вряд ли будет/останется маленьким и т. д. Его следует изменить, чтобы он был классом, если это еще не так. Все это говорит о том, что есть причины для изменения ссылочного объекта, а не для изменения существующего. Все сводится к желаемому поведению, и мы не можем знать это из показанного кода. Вопрос также неоднозначен относительно того, о чем он на самом деле просит.

Servy 29.03.2019 20:18

Переменная 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();

Visualspark 16.02.2020 05:20

Если вы хотите заменить сам объект в коллекции, выполните удаление/добавление:

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;

Другие вопросы по теме