как объект List <string>добавляет предоставленную строку - PullRequest
3 голосов
/ 29 января 2010

Кто-нибудь, пожалуйста, пролите свет на то, как реализован метод Add для

.

(как метод Add реализован для List в c #)

listobject.Add (); где List<User> listobject= new List<User>() - объявление объекта.

Я знаю, что используя List, мы можем выполнять много операций на лету, и это тоже с безопасностью типов, но меня интересует, как реализован метод id add, который заботится обо всем этом во время выполнения.

Надеюсь, он не копирует объект и не вносит коррективы при каждом добавлении, но я буду скрещивать пальцы и ждать вашего ответа:)

Ответы [ 5 ]

6 голосов
/ 29 января 2010

Используя Отражатель , вы можете точно увидеть, как он реализован.

public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}

После 'EnsureCapacity' ...

private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}

И, наконец, установщик для 'Вместимость '

public int Capacity
{
    get
    {
        return this._items.Length;
    }
    set
    {
        if (value != this._items.Length)
        {
            if (value < this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
            }
            if (value > 0)
            {
                T[] destinationArray = new T[value];
                if (this._size > 0)
                {
                    Array.Copy(this._items, 0, destinationArray, 0, this._size);
                }
                this._items = destinationArray;
            }
            else
            {
                this._items = List<T>._emptyArray;
            }
        }
    }
}
3 голосов
/ 29 января 2010

Внутренне List<T> содержит элементы в массиве. Реальная реализация (List<string>) создается в время компиляции время выполнения (спасибо @Jason за исправление), поэтому внутри будет массив строк, содержащий элементы.

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

string a = "a";
List<string> list = new List<string>();
list.Add(a); // now the item in the list and a refer to the same string instance
a = "b";     // a is now a completely new instance, the list 
             // is still referring the old one
1 голос
/ 29 января 2010

Как отмечает Фредерик, List внутренне использует массив. Он создает массив с начальным размером и, по мере добавления дополнительных элементов, если массив заполняется до предела, он копируется в больший массив. Вот почему, если вы заранее знаете, что List будет содержать много строк, это может помочь указать его начальную емкость в конструкторе .

Когда вы удаляете элементы из списка или вставляете в середину, он должен сдвинуть все элементы во внутреннем массиве, чтобы список не был особенно оптимизирован для добавления / удаления многих элементов. Возможно, вам будет лучше использовать LinkedList , который намного более эффективен при операциях добавления / удаления, но дает возможность эффективно получать доступ к элементам в списке по позиции.

Различные коллекции имеют разные реализации, которые лучше всего подходят для определенных сценариев. Для хорошего примера того, как реализованы различные коллекции, я предлагаю проверить библиотеку PowerCollections , выпущенную Wintellect. Многие из коллекций больше не актуальны в .NET 3.5 / 4.0, но они дают некоторое представление о том, как приступить к реализации коллекций.

1 голос
/ 29 января 2010

Нет, он будет работать со ссылкой на строку, иначе не было бы особого смысла использовать его, если он всегда клонировал ваши объекты.

На самом деле вы можете проверить подобные вещи в Visual Studio, используя экраны памяти, можно сравнить адрес добавленного элемента и оригинал, и вы увидите, что они указывают на одну и ту же область памяти.

0 голосов
/ 29 января 2010

Для списка метод Add будет иметь универсальный тип T, в данном случае строку. Содержимое списка будет ссылкой на исходную переменную, поэтому, если вы измените строку в списке, это изменит исходную и наоборот.

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