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

类似(伪代码):

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

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


当前回答

在c# 8.0中,你现在可以像Python一样做许多更漂亮的工作,包括反向索引和范围,例如:

int[] list = {1, 2, 3, 4, 5, 6};
var list2 = list[2..5].Clone() as int[]; // 3, 4, 5
var list3 = list[..5].Clone() as int[];  // 1, 2, 3, 4, 5
var list4 = list[^4..^0].Clone() as int[];  // reverse index

其他回答

在c# 8中,他们引入了一个新的范围和索引类型,可以这样使用:

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }

引用:

https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#ranges-and-indices https://devblogs.microsoft.com/dotnet/building-c-8-0/

这个怎么样:

public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
{
    T[] retArray = new T[endIndex - startIndex];
    for (int i = startIndex; i < endIndex; i++)
    {
        array[i - startIndex] = array[i].Clone();
    }
    return retArray;

}

然后,您需要在所有需要使用ICloneable的类上实现ICloneable接口,但这样就可以了。

我看到你想做克隆,而不仅仅是复制引用。 在这种情况下,您可以使用. select将数组成员投射到它们的克隆体。 例如,如果你的元素实现了IClonable,你可以这样做:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

注意:此解决方案需要。net Framework 3.5。

以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连接或文件/流句柄,你显然有问题,但这对任何广义深度复制都是真的。

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

这是我发现的最佳方法:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

希望有帮助!