0

这些是我无法响应正确结果的旧代码。

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()。这样对吗?还是其他原因?

4

2 回答 2

1

命名空间附带的所有扩展方法都会System.Linq创建对象的新副本(如果您愿意,可以使用深层副本)。因此,当您说在另一个内存位置创建一个新列表时,您是对的。

要确认两个对象是否不同,可以通过 unsafe 获取它们的内存地址并自己查看。这里有一些东西需要测试(如果你使用不安全的代码要小心;你需要自己处理所有的内存管理):

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);
            }
于 2018-05-02T08:09:25.510 回答
1

ToList()是一个返回列表的扩展方法。您没有将该值保存在变量中,因此尽管您调用AddRange(),但您将添加到您创建的列表中,ToList()而不是添加到您的 testList 中。

在您的第二个示例中,您正确地持有ToList()in 结果的值。

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);
于 2018-05-02T08:11:11.600 回答