列出<t> .ToArray()未按预期工作</t>

时间:2013-10-08 11:00:37

标签: c# list

当我尝试使用.ToArray()创建一个包含深层副本的数组时,我遇到了一个问题。

这是我的测试类:

public class MyClass
{
    public Color Color1;
    public MyClass(Color color)
    {
        this.Color1 = color;
    }
}

这是我用来执行List

的ToArray()的代码
List<MyClass> listColors = new List<MyClass>();
listColors.Add(new MyClass(Color.Blue));
listColors.Add(new MyClass(Color.Green));
listColors.Add(new MyClass(Color.Red));

MyClass[] arrayColors = listColors.ToArray();
arrayColors[2].Color1 = Color.Purple;

Console.WriteLine(arrayColors[2].Color1.ToString());
Console.WriteLine(listColors[2].Color1.ToString());

结果:

Color [Purple]
Color [Purple]

如您所见,我使用.ToArray()方法创建了一个数组MyClass,然后更改了此数组的第3个元素,但我不知道为什么List listColors也会更改。

我在带有.NET 2.0的Windows XP上运行此示例。

我尝试在Windows 7上运行此示例,结果如下:

Color [Purple]
Color [Red]

所以我认为,这是.NET框架的问题。

那么在.NET 2.0中是否可以像.NET 4那样进行List的深层复制?这只是一个测试类,在我的工作中,它更大。

非常感谢。

3 个答案:

答案 0 :(得分:2)

你没有创建新的MyClass对象试试这个(它给你预期的结果):

List<MyClass> listColors = new List<MyClass>();
listColors.Add(new MyClass(Color.Blue));
listColors.Add(new MyClass(Color.Green));
listColors.Add(new MyClass(Color.Red));

MyClass[] arrayColors = listColors.ToArray();
arrayColors[2] = new MyClass(Color.Purple);

Console.WriteLine(arrayColors[2].Color1.ToString());
Console.WriteLine(listColors[2].Color1.ToString());

在您的代码中,您正在更改包含Red的颜色的MyClass对象的属性,MyClass对象同时包含在列表和数组中。

答案 1 :(得分:0)

ToArray()不执行深层复制,至少不是您期望的意义。它创建一个具有相同对象的数组。我对此主题的最佳解释是:MSDN

简而言之,当源列表/目标列表/数组都是引用类型时 - 执行浅拷贝,这意味着该数组包含相同的引用。因此,您正在更改原始对象。

答案 2 :(得分:0)

好的,这里有一些与.Net 2.0一起使用的通用方法。拿你需要的那些。

public static IList<T> DeepToList<T>(IEnumerable<T> source) where T : IClonable
{
    IList<T> result = new List<T>();
    foreach (T t in source)
    {
        result.Add((T)t.Clone());
    }

    return result;
}

public static T[] DeepToArray<T>(IEnumerable<T> source) where T : IClonable
{
    IList<T> clones =  DeepToList(source);
    T[] result = new T[clones.Count];
    clones.CopyTo(result, 0);
    return result;
}

public static T[] DeepToArray<T>(IList<T> source) where T : IClonable
{
    T[] result = new T[source.Count];
    for (int i = 0; i < source.Count; i++)
    {
        result[i] = (T)source[i].Clone();
    }

    return result;
}

要使用它们,MyClass必须实施IClonable

public class MyClass : IClonable
{
    public Color Color1;
    public MyClass(Color color)
    {
        this.Color1 = color;
    }

    public object Clone()
    {
        return new MyClass(this.Color1);
    }
}

所以你可以做到,

MyColor[] arrayColors = DeepToArray(listColors)