С# Копировать массив по значению
У меня есть типизированный массив MyType[] types;
и я хочу сделать и независимую копию этого массива. я попробовал это
MyType[] types2 = new MyType[types.Length] ;
types2 = types ;
но это создает ссылку на первую. Затем я попробовал
Array.Copy( types , types2 , types.Length ) ;
но у меня такая же проблема: изменение значения в первом массиве также изменяет значение в копии.
Как я могу сделать полностью независимую или глубокую копию массива, IList или IEnumerable?
Ответы
Ответ 1
Внедрить метод clone в MyType, используя защищенный метод MemberwiseClone (выполняет мелкую копию) или используя метод глубокого клонирования. Вы можете заставить его внедрить 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
Основываясь на первом сообщении, все, что ему нужно, это "независимая копия массива". Изменения в массиве shallowCopy
не будут отображаться в массиве types
(что означает назначение элемента, что действительно является тем, что он показал выше, несмотря на то, что он сказал "глубокая копия" ). Если это соответствует вашим потребностям, оно будет иметь лучшую производительность.
MyType[] shallowCopy = (MyType[])types.Clone();
Он также упоминает "глубокую копию", которая будет отличаться для изменяемых типов, которые не являются рекурсивными агрегатами примитивов типа значений. Если MyType
реализует ICloneable
, это отлично работает для глубокой копии:
MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());
Ответ 3
Если ваш тип сериализуется, вы можете использовать методы сериализации для получения копии вашего массива (включая глубокие копии элементов):
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
Для нетерпеливых:
newarray = new List<T>(oldarray).ToArray();
Ответ 5
Я хотел сделать то же самое: сделайте копию массива по значению для таких вещей, как сортировка, чтобы я мог позже повторно инициализировать другой массив temp с исходным массивом. Изучив это, я обнаружил, что это невозможно сделать так просто. Итак, я сделал обходной путь. Я буду использовать свой собственный код ниже:
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. Я проверил это, и этот код не сортирует имена planetNames, когда я сортирую tempNames, чего я пытаюсь достичь.
Ответ 6
Если вы хотите создать копию только массива со ссылками на объекты в старом массиве (или если у вас есть массив объектов типа значения), самым простым решением является
var newArray = oldArray.ToArray()
Если вам нужна глубокая копия, у вас должен быть метод, который копирует один объект вашего типа (например, public MyType Copy(MyType obj)
). Тогда решение будет выглядеть как
var newArray = oldArray.Select(x => Copy(x)).ToArray()
Ответ 7
Я нашел, если вам просто нужна простая копия массива char, вы можете обмануть С# для выполнения копии по значению с помощью char:
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;
}
Кажется, работает для меня, но если кто-то не согласен, сообщите мне:)