假设我有一堂课
public class MyObject
{
public int SimpleInt{get;set;}
}
Run Code Online (Sandbox Code Playgroud)
我有一个List<MyObject>
,然后我ToList()
改变其中一个SimpleInt
,将我的更改传播回原始列表.换句话说,以下方法的输出是什么?
public void RunChangeList()
{
var objs = new List<MyObject>(){new MyObject(){SimpleInt=0}};
var whatInt = ChangeToList(objs );
}
public int ChangeToList(List<MyObject> objects)
{
var objectList = objects.ToList();
objectList[0].SimpleInt=5;
return objects[0].SimpleInt;
}
Run Code Online (Sandbox Code Playgroud)
为什么?
P/S:如果发现它似乎很明显,我很抱歉.但我现在没有编译器...
Luk*_*keH 203
是的,ToList
将创建一个新列表,但因为在这种情况下MyObject
是一个引用类型,所以新列表将包含与原始列表相同的对象的引用.
更新SimpleInt
新列表中引用的对象的属性也会影响原始列表中的等效对象.
(如果MyObject
声明为a struct
而不是a,class
则新列表将包含原始列表中元素的副本,并且更新新列表中元素的属性不会影响原始列表中的等效元素.)
Chr*_*s S 58
来自Reflector'd来源:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
Run Code Online (Sandbox Code Playgroud)
所以是的,您的原始列表将不会更新(即添加或删除),但引用的对象将会更新.
SLa*_*aks 31
ToList将始终创建一个新列表,该列表不会反映对集合的任何后续更改.
但是,它会反映对象本身的变化(除非它们是可变的结构).
换句话说,如果使用其他对象替换原始列表中的对象,ToList
则仍将包含第一个对象.
但是,如果修改原始列表中的某个对象,ToList
则仍将包含相同(已修改)的对象.
LBu*_*kin 11
是的,它会创建一个新列表.这是设计的.
该列表将包含与原始可枚举序列相同的结果,但具体化为持久性(内存中)集合.这允许您多次使用结果,而不会产生重新计算序列的成本.
LINQ序列的美妙之处在于它们是可组合的.通常,IEnumerable<T>
您获得的是结合多个过滤,排序和/或投影操作的结果.扩展方法一样ToList()
,并ToArray()
让您的计算机序列转换成标准的集合.
Dou*_*las 11
接受的答案根据他的例子正确地解决了OP的问题.但是,它仅适用ToList
于具体集合时; 当源序列的元素尚未实例化时(由于延迟执行),它不成立.如果是后者,每次调用ToList
(或枚举序列)时,您可能会获得一组新项目.
以下是OP代码的改编,以演示此行为:
public static void RunChangeList()
{
var objs = Enumerable.Range(0, 10).Select(_ => new MyObject() { SimpleInt = 0 });
var whatInt = ChangeToList(objs); // whatInt gets 0
}
public static int ChangeToList(IEnumerable<MyObject> objects)
{
var objectList = objects.ToList();
objectList.First().SimpleInt = 5;
return objects.First().SimpleInt;
}
Run Code Online (Sandbox Code Playgroud)
虽然上面的代码可能看似人为,但这种行为在其他场景中可能会出现一个微妙的错误.请参阅我的另一个示例,了解导致任务重复生成的情况.
只是偶然发现这个旧帖子,想到加上我的两分钱.通常,如果我有疑问,我会在任何对象上快速使用GetHashCode()方法来检查身份.所以对于上面 -
public class MyObject
{
public int SimpleInt { get; set; }
}
class Program
{
public static void RunChangeList()
{
var objs = new List<MyObject>() { new MyObject() { SimpleInt = 0 } };
Console.WriteLine("objs: {0}", objs.GetHashCode());
Console.WriteLine("objs[0]: {0}", objs[0].GetHashCode());
var whatInt = ChangeToList(objs);
Console.WriteLine("whatInt: {0}", whatInt.GetHashCode());
}
public static int ChangeToList(List<MyObject> objects)
{
Console.WriteLine("objects: {0}", objects.GetHashCode());
Console.WriteLine("objects[0]: {0}", objects[0].GetHashCode());
var objectList = objects.ToList();
Console.WriteLine("objectList: {0}", objectList.GetHashCode());
Console.WriteLine("objectList[0]: {0}", objectList[0].GetHashCode());
objectList[0].SimpleInt = 5;
return objects[0].SimpleInt;
}
private static void Main(string[] args)
{
RunChangeList();
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
并在我的机器上回答 -
基本上列表中携带的对象在上面的代码中保持不变.希望这种方法有所帮助
归档时间: |
|
查看次数: |
100566 次 |
最近记录: |