#c# #linq-to-objects
#c# #linq-to-objects (привязка к объектам)
Вопрос:
У меня есть IList пользователей
private IList<User> _Players
У меня есть способ удалить конкретного пользователя из списка
public virtual void RemovePlayer(User User)
{
int index=_Players.Select(T=>T.ID).ToList().IndexOf(User.ID);
_Players.RemoveAt(index);
}
Я хотел бы знать, есть ли более простой способ удалить пользователя из этого списка
Ответ №1:
Как насчет этого? Используйте это, если ваш параметр User
не является частью _Players
.
_Players.Remove(_Players.SingleOrDefault(x => x.ID == User.ID));
SingleOrDefault()
Гарантирует, что если совпадение не найдено, возвращается значение null. При попытке удалить null ошибка не возникает и не выдается.
Ответ №2:
Если User
используемые вами объекты хранятся в _ Players
списке (те же ссылки на объекты), вы можете просто сделать
_Players.Remove(user);
В противном случае, если совпадает только идентификатор, вы можете сделать:
_Players.RemoveAll( p => p.ID == user.ID);
Комментарии:
1. removeAll не работает с IList, что и было первоначальным вопросом.
2. Этот ответ не относится к исходному вопросу.
Ответ №3:
Существует два сценария, user
переменная, которую вы передаете RemovePlayer
- на самом деле содержится в вашем списке
- имеет то же
ID
значение, но не является тем же объектом.
Из вашего примера кода невозможно сказать.
В первом случае просто вызовите _Players.Remove(user)
. Во втором случае реализуйте System.IEquatable<User>
интерфейс на User
, чтобы определить значение по умолчанию EqualityComparer<User>
, а затем снова вызовите _Players.Remove(user)
. Этот второй сценарий работает в обоих случаях.
Комментарии:
1. это решение очень помогает, потому что я использую generics и могу удалять объекты без необходимости знать свойства, которые они содержат.
2. @David On ИТАК, люди голосуют, основываясь в первую очередь на оценке постера, а не на ответе; это хорошо видно здесь 🙂
Ответ №4:
Зависит от того, внедрили ли вы IEquatable
для своего пользователя функцию сравнения по ID
, тогда вы могли бы просто сделать _Players.Remove(user)
.
В противном случае:
var doomed = _Players.FirstOrDefault(p => p.ID == user.ID);
if (doomed != null)
_Players.Remove(doomed);
Ответ №5:
Только в том случае, если у вас есть List<T>
:
Все упомянутые алгоритмы с SingleOrDefault()
/ FirstOrDefault()
требуют двух обходов по списку:
1) первый, кто найдет элемент по критериям
2) второй, чтобы найти индекс элемента по его значению, найденному на шаге # 1
Немного эффективнее сделать вот так вместо этого:
int index = list.FindIndex(i => criteria);
if (index >= 0)
list.RemoveAt(index);
Ответ №6:
Просто хотел сделать то же самое, но не смог найти стандартный способ.
Решил сам написать код для своих списков int. Этот маленький не будет выполнять двойной проход по списку!
Вы можете заменить int
на object
для работы с классами.
public static bool FindAndRemoveFirst(this ICollection<int> list, Func<int, bool> predicate)
{
var en = list.GetEnumerator();
while (en.MoveNext())
{
if (predicate(en.Current))
{
list.Remove(en.Current);
return true;
}
}
return false;
}