Почему у меня есть результат ошибки при использовании IList (). ToList (). AddRange ()? - PullRequest
0 голосов
/ 02 мая 2018

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

IList<string> testList=new List<string>();
testList.Add("string1");
var testList2=new List<string>(testList);
testList.ToList().AddRange(testList2);

Я ожидаю, что в testList есть два элемента, но на самом деле он содержит только один элемент; Если я поменяю код на новый стиль, он может получить правильный результат. Пример:

IList<string> testList=new List<string>();
testList.Add("string1");
var testList2=new List<string>(testList);
var result=testList.ToList();
result.AddRange(testList2);

В результате он успешно имеет два элемента. Я думаю, причина в том, что iList (). ToList () создает новый список в другом месте, как результат параметра, который не зависит от iList (). Это правильно? или другие причины?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

ToList() - это метод расширения, который возвращает список. Вы не храните это значение в переменной, поэтому, хотя вы вызываете AddRange(), вы добавляете в список, который вы создали в ToList(), а не в свой testList.

Во втором примере вы правильно удерживаете значение ToList() в результате.

var result=testList.ToList();
result.AddRange(testList2);

У вас есть несколько вариантов ...

// option 1 declare testList as a List not IList
List<string> testList = new List<string>();
testList.AddRange(testList2);

// option 2 cast testList as a List
((List<string>)testList).AddRange(testList2);
0 голосов
/ 02 мая 2018

Все методы расширения, поставляемые с пространством имен System.Linq, создают новую копию объекта (глубокую копию, если хотите). Итак, вы правы, когда говорите, что новый список создается в другом месте памяти.

Чтобы проверить, отличаются ли два объекта, вы можете получить их адреса памяти через небезопасные и убедиться в этом сами. Вот что нужно проверить (будьте осторожны, если вы используете небезопасный код; вам нужно самостоятельно управлять всем управлением памятью):

unsafe
            {
                IList<string> testList = new List<string>();
                testList.Add("string1");
                var testList2 = new List<string>(testList);
                testList.ToList().AddRange(testList2);

                TypedReference original = __makeref(testList);
                IntPtr originalPointer = **(IntPtr**)(&original);

                var isThisANewList = testList;

                TypedReference newReferenceOnly = __makeref(testList);
                IntPtr newReferenceOnlyPointer = **(IntPtr**)(&newReferenceOnly);

                var copy = testList.ToList();

                TypedReference deepCopy = __makeref(copy);
                IntPtr deepCopyPointer = **(IntPtr**)(&deepCopy);
            }
...