为什么我使用IList()。toList()。AddRange()?

时间:2018-05-02 07:58:24

标签: asp.net list 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()在其他地方创建一个新的List,作为param结果,独立于iList()。这样对吗?或其他原因?

2 个答案:

答案 0 :(得分:1)

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);
            }

答案 1 :(得分:1)

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);