Почему у меня есть ошибка в результате использования IList(). ToList().AddRange()?
Это мой старый код, который не может дать правильный результат.
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 ответа
Все методы расширения, которые идут с 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);
}
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);