2013-06-28 2 views
2

Мне интересно, как можно доказать, что инфраструктура .NET работает за кулисами.Список <String> ByRef

У меня есть метод, который принимает параметр List<String> originalParameterList.

В моем методе у меня есть еще один List<String> newListObj если я следующее:

List<String> newListObj = originalParameterList 
    newListObj.Add(value); 
    newListObj.Add(value1); 
    newListObj.Add(value2); 

Количество в originalParameterList растет (+3).

Если я это сделать:

List<String> newListObj = new List<String>(originalParamterList); 

newListObj.Add(value); 
newListObj.Add(value1); 
newListObj.Add(value2); 

Количество в originalParameterList остается SAMES (+0).

Я также обнаружил, что этот код ведет себя так же:

List<String> newListObj = new List<String>(originalParamterList.ToArray()); 

newListObj.Add(value); 
newListObj.Add(value1); 
newListObj.Add(value2); 

Количество в originalParameterList остается SAMES (+0).

Вопрос в том, есть ли способ увидеть, что .NET Framework делает за кулисами окончательно?

+0

Вы можете изучить IL. Кроме того, вы передаете ссылки на новый список при его создании. Вы не влияете на исходный список. –

+0

Внимательно прочитайте [** MSDN **] (http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx). Вы также можете использовать отражатель, например ['ILSpy'] (http://ilspy.net/). Другим ресурсом является [спецификация языка C#] (http://www.ecma-international.org/publications/standards/Ecma-334.htm). –

+0

см. [Http://stackoverflow.com/questions/186891/why-use-ref-keyword-when-passing-an-object](http://stackoverflow.com/questions/186891/why-use-ref- keyword-when-through-an-object) – saamorim

ответ

0

Обычно в документации должна быть предоставлена ​​достаточная информация для использования API.

В вашем конкретном примере, документация для public List(IEnumerable<T> collection) говорит (курсив мой):

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

Для справки здесь исходный код для конструктора:

public List (IEnumerable <T> collection) 
{ 
    if (collection == null) 
     throw new ArgumentNullException ("collection"); 

    // initialize to needed size (if determinable) 
    ICollection <T> c = collection as ICollection <T>; 
    if (c == null) { 
     _items = EmptyArray<T>.Value;; 
     AddEnumerable (collection); 
    } else { 
     _size = c.Count; 
     _items = new T [Math.Max (_size, DefaultCapacity)]; 
     c.CopyTo (_items, 0); 
    } 
} 

void AddEnumerable (IEnumerable <T> enumerable) 
{ 
    foreach (T t in enumerable) 
    { 
     Add (t); 
    } 
} 
0

Самый простой способ сделать это просто пойти в MSDN

http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx

Он говорит, что

Инициализирует новый экземпляр Класс List, содержащий элементы, скопированные из указанной коллекции, и обладает достаточной емкостью для размещения количества скопированных элементов.

так внутренне он просто добавляет все элементы прошедшего IEnumerable в новый список.Он также говорит, что

это О (п) операции

, что означает, что никакие оптимизации не предполагается.

0

Это потому, что случай frist вы ссылались на исходный список (так как это ссылочный тип), и вы изменили его коллекцию с помощью newListObj. Во втором и третьем случае вы скопировали коллекцию исходных объектов через конструктор списка List Class, и вы изменили новую коллекцию, которая не влияет на оригинал.

0

Как уже говорилось, существуют различные инструменты, позволяющие вам изучить исходный код платформы .NET. Я лично предпочитаю dotPeek from JetBrains, что бесплатно.

В конкретном случае, о котором вы упомянули, я думаю, когда вы передаете список в конструктор другого списка, этот список копируется. Если вы просто присваиваете одну переменную другой, эти переменные просто ссылаются на один и тот же список.

0

Это код из списка constrcutor:

public List(IEnumerable<T> collection) 
{ 
    if (collection == null) 
    { 
     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); 
    } 
    ICollection<T> collection2 = collection as ICollection<T>; 
    if (collection2 != null) 
    { 
     int count = collection2.Count; 
     this._items = new T[count]; 
     collection2.CopyTo(this._items, 0); 
     this._size = count; 
     return; 
    } 
    this._size = 0; 
    this._items = new T[4]; 
    using (IEnumerator<T> enumerator = collection.GetEnumerator()) 
    { 
     while (enumerator.MoveNext()) 
     { 
      this.Add(enumerator.Current); 
     } 
    } 
} 

Как вы можете видеть, когда звонит costructor, который принимает IEnumerable копирует все данные себе.

1

Вы можете загрузить свою сборку в ILDASM и (при загрузке), найти свой метод и дважды щелкнуть по нему, он покажет код cil этого метода. Просто введите «IL» в меню запуска Windows в поиске.

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

 private void GetList(List<string> lst) 
     { 
      List<string> NewList = lst.Cast<string>().ToList(); 
      NewList.Add("6"); 
      //not same values. 
      //or.... 
      List<string> NewList = lst.ConvertAll(s => s); 
      NewList.Add("6"); 
      //again different values 

     } 
Смежные вопросы