У меня есть массив X из 10 элементов. Я хотел бы создать новый массив, содержащий все элементы из X, которые начинаются с индекса 3 и заканчиваются индексом 7. Конечно, я могу легко написать цикл, который сделает это для меня, но я хотел бы сохранить мой код как можно более чистым , Есть ли в C # метод, который может сделать это для меня?
Что-то вроде (псевдокод):
Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)
Array.Copy
не соответствует моим потребностям . Мне нужно, чтобы элементы в новом массиве были клонами. Array.copy
это просто memcpy
эквивалент C-Style , это не то, что я ищу.
Ответы:
Вы можете добавить его как метод расширения:
Обновление повторного клонирования (что не было очевидно в исходном вопросе). Если вы действительно хотите глубокого клона; что-то вроде:
Это требует, чтобы объекты были сериализуемыми (
[Serializable]
илиISerializable
), хотя. Вы можете легко заменить любой другой сериализатором в соответствующих случаях -XmlSerializer
,DataContractSerializer
, Protobuf-сети и т.д.Обратите внимание, что глубокий клон сложен без сериализации; в частности,
ICloneable
трудно доверять в большинстве случаев.источник
Вы можете использовать
Array.Copy(...)
для копирования в новый массив после его создания, но я не думаю, что есть метод, который создает новый массив и копирует диапазон элементов.Если вы используете .NET 3.5, вы можете использовать LINQ:
но это будет несколько менее эффективно.
Посмотрите этот ответ на аналогичный вопрос для вариантов для более конкретных ситуаций.
источник
Вы рассматривали возможность использования
ArraySegment
?http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx
источник
IEnumerable<T>
и множество других полезных интерфейсов.ArraySegment
чтобы ответить на оригинальный вопрос?IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
Я вижу, вы хотите делать клонирование, а не просто копировать ссылки. В этом случае вы можете использовать
.Select
для проецирования элементов массива на их клонов. Например, если ваши элементы реализованы,IClonable
вы можете сделать что-то вроде этого:Примечание. Для этого решения требуется .NET Framework 3.5.
источник
IEnumerable
. Я могу получитьIEnumerable
,IList
,IArray
и т.д. ... с минимальной суетой, рядный , если мне нужно. Если мне не нужна глубокая копия, я просто удаляюSelect
. ПадениеSkip
илиTake
позволяет мне контролировать диапазон. В качестве альтернативы, я могу смешать это сSkipWhile
и / илиTakeWhile
.Следующий код делает это в одну строку:
источник
В C # 8 они ввели новый
Range
иIndex
типисточник
источник
Основываясь на ответе Марка, но добавляя желаемое поведение клонирования
И если реализация ICloneable слишком похожа на тяжелую работу, рефлексивную, использующую библиотеку Ховарда Страндена с возможностью копирования, чтобы выполнить тяжелую работу.
Обратите внимание, что реализация OX.Copyable работает с любым из:
Так что это должно охватывать практически любую ситуацию, которая у вас есть. Если вы клонируете объекты, где подграф содержит такие вещи, как соединения БД или дескрипторы файлов / потоков, у вас, очевидно, есть проблемы, но это верно для любой обобщенной глубокой копии.
Если вы хотите использовать какой-то другой подход глубокого копирования, в этой статье перечислено несколько других, поэтому я бы посоветовал не пытаться писать свой собственный.
источник
Вы можете сделать это довольно легко;
источник
Я думаю, что код, который вы ищете:
Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)
источник
В качестве альтернативы копированию данных вы можете создать оболочку, которая дает вам доступ к части исходного массива, как если бы она была копией части массива. Преимущество состоит в том, что вы не получаете другую копию данных в памяти, а недостатком является небольшая нагрузка при доступе к данным.
Использование:
источник
Array.ConstrainedCopy будет работать.
источник
Там нет единого метода, который будет делать то, что вы хотите. Вам нужно будет сделать метод клона доступным для класса в вашем массиве. Затем, если LINQ является опцией:
источник
Как насчет использования Array.ConstrainedCopy :
Ниже мой оригинальный пост. Он не будет работать
Вы можете использовать Array.CopyTo :
источник
Как насчет этого:
Затем вам нужно реализовать интерфейс ICloneable на всех классах, на которых вы хотите это использовать, но это должно быть сделано.
источник
Я не уверен, насколько глубоко это на самом деле, но:
MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()
Это немного накладные расходы, но это может исключить ненужный метод.
источник
C # 8 предоставляет функцию, называемую Range, чтобы получить подарри от начального до конечного индекса. Вы можете использовать это так.
источник
Что касается клонирования, я не думаю, что сериализация вызывает ваши конструкторы. Это может нарушить инварианты класса, если вы делаете интересные вещи в ctor'е.
Кажется, безопаснее ставить виртуальные методы-клоны, вызывающие конструкторы копирования.
источник
Клонирование элементов в массиве - это не то, что можно сделать универсальным способом. Вы хотите глубокое клонирование или простую копию всех участников?
Давайте перейдем к подходу «наилучшее усилие»: клонирование объектов с использованием интерфейса ICloneable или двоичная сериализация:
Это не идеальное решение, потому что просто нет ни одного, который будет работать для любого типа объекта.
источник
Вы можете взять уроки, сделанные Microsoft:
а потом
источник
Я нашел оптимальный способ сделать это:
Надеюсь, поможет!
источник
использовать метод расширения:
и вы можете использовать его
источник
Код из System.Private.CoreLib.dll:
источник
Он не соответствует вашему требованию клонирования, но кажется более простым, чем многие ответы:
источник
источник