我有一个包含10个元素的数组X。我想创建一个新数组,包含X中从索引3开始并在索引7结束的所有元素。当然,我可以很容易地写一个循环,将它为我,但我想保持我的代码尽可能干净。c#中有一个方法可以帮我做这个吗?

类似(伪代码):

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

数组中。拷贝不符合我的需要。我需要在新数组中的项目是克隆。数组中。copy只是一个c风格的memcpy等效,这不是我要找的。


当前回答

那么使用数组呢?ConstrainedCopy:

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

以下是我的原帖。这是行不通的

你可以使用数组。CopyTo:

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

其他回答

你可以添加它作为一个扩展方法:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

更新重新克隆(这在最初的问题中并不明显)。如果你真的想要一个深度克隆;喜欢的东西:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

不过,这确实要求对象是可序列化的([serializable]或ISerializable)。您可以轻松地替换任何其他合适的序列化器——XmlSerializer、DataContractSerializer、protobuf-net等等。

注意,深度克隆在没有序列化的情况下是很棘手的;特别是,ICloneable在大多数情况下是很难信任的。

我认为你要找的代码是:

阵列。复制(oldArray, 0, newArray,开始,EndIndex -开始)

我不确定它到底有多深,但是:

MyArray ToList < TSource >()。GetRange (beginningIndex, endIndex) . ToArray ()

这是一些开销,但它可能会减少一个不必要的方法。

以Marc的回答为基础,但加入了想要的克隆行为

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}

如果实现ICloneable太辛苦了,那么可以使用Håvard Stranden的Copyable库来完成所需的繁重工作。

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}

注意,OX.Copyable实现适用于以下任何一种:

然而,为了让自动复制工作,以下语句之一必须成立,例如: 它的类型必须有一个无参数构造函数,或者 它必须是可复制的,或者 它必须为其类型注册一个IInstanceProvider。

所以这应该适用于你遇到的任何情况。如果你克隆的对象子图中包含db连接或文件/流句柄,你显然有问题,但这对任何广义深度复制都是真的。

如果你想使用其他深度复制方法,本文列出了其他几种方法,所以我建议你不要尝试自己编写。

克隆数组中的元素并不是一种通用的方法。您想要深度克隆还是所有成员的简单副本?

让我们采用“尽最大努力”的方法:使用ICloneable接口或二进制序列化克隆对象:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

这并不是一个完美的解决方案,因为没有一个解决方案适用于任何类型的对象。