C#按值复制数组

时间:2009-07-31 22:33:33

标签: c# arrays

我有一个类型化数组MyType[] types; 我想制作这个数组的独立副本。我试过这个

MyType[] types2 = new MyType[types.Length] ;

types2 = types ;

但这会创建对第一个的引用。然后我尝试了

Array.Copy( types , types2 , types.Length ) ;

但我遇到了同样的问题:更改第一个数组中的值也会更改副本中的值。

如何制作数组,IList或IEnumerable的完全独立或深层副本?

8 个答案:

答案 0 :(得分:11)

根据第一篇文章,他所需要的只是“数组的独立副本”。对shallowCopy数组本身的更改不会出现在types数组中(意思是元素赋值,这实际上是他在上面展示的内容,尽管说“深拷贝”)。如果这符合您的需求,它将具有最佳性能。

MyType[] shallowCopy = (MyType[])types.Clone();

他还提到了一个“深层复制”,它对于不是基元的递归值类型聚合的可变类型会有所不同。如果MyType实现ICloneable,则这适用于深层复制:

MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());

答案 1 :(得分:9)

使用受保护的方法MemberwiseClone(执行浅拷贝)或使用深度克隆技术在MyType上实现克隆方法。您可以让它实现ICloneable,然后编写几个扩展方法来克隆相应的集合。

interface ICloneable<T>
{
    T Clone();
}

public static class Extensions
{
    public static T[] Clone<T>(this T[] array) where T : ICloneable<T>
    {
        var newArray = new T[array.Length];
        for (var i = 0; i < array.Length; i++)
            newArray[i] = array[i].Clone();
        return newArray;
    }
    public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T>
    {
        foreach (var item in items)
            yield return item.Clone();
    }
}

您必须执行此操作,因为在使用Array.Copy时创建新数组时,它会复制引用,而不是引用的对象。每种类型都有责任自我复制。

答案 2 :(得分:8)

对于不耐烦的人:

newarray = new List<T>(oldarray).ToArray();

答案 3 :(得分:7)

如果您的类型是可序列化的,您可以使用序列化技术获取数组的副本(包括项目的深层副本):

private static object GetCopy(object input)
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, input);
        stream.Position = 0;
        return formatter.Deserialize(stream);
    }
}

使用它:

MyType[] items = new MyType[2];
// populate the items in the array

MyType[] copies = (MyType[])GetCopy(items);

答案 4 :(得分:3)

我想做同样的事情:按照排序等方式为数组制作一个数组副本,这样我以后可以用原始源数组重新初始化另一个临时数组。在研究了这个之后,我发现这不能简单地完成。所以,我做了一个解决方法。我将在下面使用我自己的代码:

string[] planetNames = new string[] { "earth", "venus", "mars" };

string[] tempNames = new string[planetNames.Length];

for (int i = 0; i < planetNames.Length; i++)
{
     tempNames[i] = planetNames[i];
}

planetNames 是我的源数组。 tempNames 是我稍后将独立于planetNames排序的数组。我已对此进行了测试,当我对 tempNames 进行排序时,此代码不会对 planetNames 进行排序。

答案 5 :(得分:1)

如果你想创建一个只包含引用旧数组中对象的数组的副本(或者如果你有值类型对象的数组),那么最简单的解决方案是

var newArray = oldArray.ToArray()

如果你想要深层复制,你应该有一个方法来复制你的类型的单个对象(例如public MyType Copy(MyType obj))。然后解决方案看起来像

var newArray = oldArray.Select(x => Copy(x)).ToArray()

答案 6 :(得分:0)

我发现如果你只是想要一个简单的char数组副本,你可以使用char来欺骗C#按值进行复制:

char[] newchararray = new char[desiredchararray.Length];

for (int k = 0; k < desiredchararray.Length; k++)
{

   char thecharacter = newchararray[k];
   newchararray[k] = thecharacter;
   oldchararray[k] = oldchararray[k] + 1;

}

似乎为我工作,但如果有人不同意,请告诉我:)

答案 7 :(得分:0)

在这种情况下复制数组的值是数字

int[] arr = { 1, 2, 3, 4, 5 };
int[] copyArr = new int[arr.Length];
for (int i = 0; i <arr.Length; i++)
{
    copyArr[i]=arr[arr.Length-i-1];
}
Console.WriteLine(string.Join(" ",arr));**