Списки клонов и массивы объектов в C#
Это последнее сообщение, которое я напишу о клонах, по крайней мере на некоторое время. Некоторые классы коллекций уже могут создавать клоны. Например, массив может клонировать сам, хотя результат всегда является мелким клоном. В этом примере показано, как добавить методы расширения, которые позволяют массивам и спискам делать как мелкие, так и глубокие клоны.
В следующем коде показаны новые методы расширения. (Это упрощенные версии, основанные на комментарии ниже Э. Андерсона.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Возвращает глубокий клон списка. public static List<T> DeepClone<T>(this List<T> items) { var query = from T item in items select item.DeepClone(); return new List<T>(query); } // Возвращаем глубокий клон массива. public static T[] DeepClone<T>(this T[] items) { var query = from T item in items select item.DeepClone(); return query.ToArray(); } // Возвращаем неглубокий клон списка. public static List<T> ShallowClone<T>(this List<T> items) { return new List<T>(items); } // Возвращаем неглубокий клон массива. public static T[] ShallowClone<T>(this T[] items) { return (T[])items.Clone(); } |
Все эти методы являются общими, поэтому они принимают параметр типового типа T, который представляет тип объектов в списке или массиве.
Первый метод делает глубокий клон списка. Он создает запрос LINQ, который выполняет итерацию через элементы в списке и вызывает метод DeepClone для каждого. эта версия DeepClone описана в сообщении
Альтернативной стратегией будет требование, чтобы тип T реализовал ICloneable, а затем вызывается метод Clone объекта. К сожалению, метод Clone, требуемый ICloneable, не обязательно должен быть глубоким клоном, поэтому в некоторых случаях результат может быть мелким клоном.
Первый представленный здесь метод передает запрос LINQ в конструктор нового списка. Этот конструктор может принимать IEnumerable в качестве параметра и использовать его для создания элементов в новом списке.
Второй метод расширения похож на первый, за исключением того, что он работает для массива вместо списка. Он использует аналогичный запрос LINQ, а затем просто вызывает его метод ToArray для преобразования элементов, выбранных запросом в массив.
Третий метод делает мелкие клоны объектов в списке. Он передает исходный список в конструктор нового списка. Этот конструктор использует элементы для инициализации нового списка.