в какой ситуации элемент в System . Collections . Generic . List не будет успешно удален?Коллекции.Универсальный.Список не будет успешно удален?

#c# #.net #vb.net #list #generic-list

#c# #.net #vb.net #Список #generic-list

Вопрос:

в какой ситуации элемент в System . Collections . Generic . List не будет успешно удален?Коллекции.Универсальный.Список не будет успешно удален?

Из http://msdn.microsoft.com/en-us/library/cd666k3e.aspx:

значение true, если элемент успешно удален; в противном случае значение false. Этот метод также возвращает false, если элемент не был найден в списке (из T).

То, как они формулируют это, заставляет меня думать, что возможно, что операция удаления элемента, найденного в списке (из T), действительно может завершиться неудачей, отсюда и этот вопрос.

Комментарии:

1. Я понимаю, что это сбой, если элемент не был найден, но мне также интересно, как еще это может привести к сбою… Хороший вопрос 🙂

Ответ №1:

Смотрим на систему.Коллекции.Универсальный.Источник списка в Reflector, похоже, что элемент, не найденный в коллекции, действительно является единственным способом для Remove вернуть false .

 int index = this.IndexOf(item);
if (index >= 0)
{
    this.RemoveAt(index);
    return true;
}
return false;
  

Ответ №2:

 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public bool Remove(T item)
{
    int index = this.IndexOf(item);
    if (index >= 0)
    {
        this.RemoveAt(index);
        return true;
    }
    return false;
}
  

Приведенный выше код с помощью reflector. Не будет удален, только если его не было в коллекции. Я предполагаю, что несоответствие документации / языка.

Ответ №3:

Да, это возможно, если вы пытаетесь удалить элемент, которого нет в списке — он классифицируется как сбой и возвращает false, чтобы показать вам, что ничего не было удалено.

Это может быть полезно, если вы затем захотите выполнить другой код, если что-то действительно было удалено.

Обновление: если ваш класс реализует IEquality и это выдает исключение, код допускает выброс, так как в нем нет возможности вернуться.

В сочетании с другими, публикующими отраженный источник, возвращает false только тогда, когда он не может найти элемент.

Обновление: далее к чужому источнику. Если вы посмотрите на IndexOf цепочку методов, вы увидите, что это сводится к равенству и не делает ничего особенного.

List.Remove:

 public bool Remove(T item)
{
    int num = this.IndexOf(item);
    if (num >= 0)
    {
        this.RemoveAt(num);
        return true;
    }
    return false;
}
  

Список.indexOf:

 public int IndexOf(T item)
{
    return Array.IndexOf<T>(this._items, item, 0, this._size);
}
  

Массив.indexOf:

 public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
    if (array == null)
    {
        throw new ArgumentNullException("array");
    }
    if (startIndex < 0 || startIndex > array.Length)
    {
        throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
    }
    if (count < 0 || count > array.Length - startIndex)
    {
        throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
    }
    return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
}
  

EqualityComparer.indexOf:

 internal virtual int IndexOf(T[] array, T value, int startIndex, int count)
{
    int num = startIndex   count;
    for (int i = startIndex; i < num; i  )
    {
        if (this.Equals(array[i], value))
        {
            return i;
        }
    }
    return -1;
}
  

Весь код из ILSpy, нет, благодаря Red Gate 🙂

Комментарии:

1. В цитируемых документах MSDN указано, что он возвращает false, если элемент не был найден в списке, а также если он не был успешно удален…

Ответ №4:

В исходном коде Mono для сравнения:

https://github.com/mono/mono/raw/master/mcs/class/corlib/System.Коллекции.Generic/List.cs

 public bool Remove (T item)
{
    int loc = IndexOf (item);
    if (loc != -1)
        RemoveAt (loc);

    return loc != -1;
}
  

Итак, документация слишком нечеткая