Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从C#中的现有数组中获取子数组而无需复制?_C#_Arrays - Fatal编程技术网

如何从C#中的现有数组中获取子数组而无需复制?

如何从C#中的现有数组中获取子数组而无需复制?,c#,arrays,C#,Arrays,我的问题与之类似,尽管在我的案例中有一点不同的概念非常重要——我不能使用内存复制 假设我有10000个元素的数组X,我需要一个数组Y,它将包含X中的9000个元素,从X的索引500开始 但是我不想将X的一部分复制到新数组Y,所以我不想使用array.copy、array.Clone、System.Block.copy、IEnumerables等。我想Y引用X-Y[0]实际上是X[500],Y[1]对应于X[501],…,Y[9000]是X[9500] 因此,例如,改变X[100]的值将同时改变Y

我的问题与之类似,尽管在我的案例中有一点不同的概念非常重要——我不能使用内存复制

假设我有10000个元素的数组
X
,我需要一个数组
Y
,它将包含
X
中的9000个元素,从
X
的索引500开始

但是我不想将
X
的一部分复制到新数组
Y
,所以我不想使用array.copy、array.Clone、System.Block.copy、IEnumerables等。我想
Y
引用
X-Y[0]
实际上是
X[500]
Y[1]
对应于
X[501]
,…,
Y[9000]
X[9500]


因此,例如,改变
X[100]
的值将同时改变
Y[600]
的值。如何在C#中实现这一点?

您可以使用以下内容将其包装到另一个对象中:

class View<T>
{
     private T[] _array;
     private long _start;
     private long _length;
     public View(T[] array, long start, long length) { ... }
     public T this[long index] 
     {
         get 
         {
             if (/*do bounds check here*/) 
             {
                 return _array[_start + index];
             }    
         }
     }
}
类视图
{
专用T[]_数组;
私人长期启动;
私人长裤;
公共视图(T[]数组,长开始,长长度){…}
这是什么[长索引]
{
得到
{
如果(/*在此处进行边界检查*/)
{
返回_数组[_开始+索引];
}    
}
}
}
这不是一个数组,而是一个数组的投影。

您可以使用一个数组。下面是一个例子:

String[] X = { "one", "two", "three", "four", "five"};

ArraySegment<String> arraySegment = new ArraySegment<String>(X, 1,3); // will contain {"two", "three", "four"}
arraySegment.Array[arraySegment.Offset + 1] = "3"; // X will contain { "one", "two", "3", "four", "five"};
                             // and arraySegment.Array will contain {"two", "3", "four"}
String[]X={“一”、“二”、“三”、“四”、“五”};
ArraySegment ArraySegment=新的ArraySegment(X,1,3);//将包含{“二”、“三”、“四”}
arraySegment.Array[arraySegment.Offset+1]=“3”//X将包含{“一”、“二”、“三”、“四”、“五”};
//数组将包含{“2”、“3”、“4”}
遗憾的是,
ArraySegment
是密封的,否则您可以使用适当的数组语法(如索引器等)轻松地对其进行扩展

如果我是你,我会选择
ArraySegment
,如果它没有适当的要求,比如
ElementAt(n)
效率太低,就实施一个更好的实现。例:

public static class ArrayExtensions 
{
  // Getter using underlying array
  public static T GetValueAt<T>(this ArraySegment<T> array, int index)
  { // No safe checks here, would recommend them in production though
    return array.Array[array.Offset + index];
  }
  // Setter using underlying array
  public static void SetValueAt<T>(this ArraySegment<T> array, int index, T value)
  { // maybe we should check that the calculated index is valid? Or just blow up?
    array.Array[array.Offset + index] = value;
  }
}
公共静态类ArrayExtensions
{
//使用底层数组的Getter
公共静态T GetValueAt(此ArraySegment数组,int索引)
{//这里没有安全检查,不过我建议在生产中使用
返回array.array[array.Offset+index];
}
//使用底层数组的Setter
公共静态void SetValueAt(此数组分段数组,int索引,T值)
{//也许我们应该检查计算的索引是否有效?或者干脆放大?
array.array[array.Offset+index]=值;
}
}

当然,你可以使用<代码>不安全的< /C>操作(就像C++指针),但是不推荐。你有没有考虑过制作一个像数组一样的简单包装器?它不是一个数组,但是如果您编写代码使用包装器,那么您可以为底层较大数组的较小片段创建包装器。为什么不能使用内存复制?有什么原因不能传递偏移量(可能是包装的一部分,如@LasseV.Karlsen所建议的)?通过复制,他将有两个不同的数组+复制的开销,如果不能复制元素,这两个数组都可能是不需要的(他没有说为什么,这只是我自己对问题的看法),那么,最初选择将阵列用作存储可能是错误的?取决于您如何使用它,您可以实现
IEnumerable
,同时只在一个列表中保存/添加/删除项。我认为数组索引不能是长的,只能是int(在数字上),我会将视图设为一个结构,因为它可以有效地保存2个32位值和一个内存引用,使它更便宜。此外,我会将字段设置为只读,但除此之外,这正是我自己选择的解决方案。谢谢,看起来很有希望:)@xcoder37为了完整性,请添加对
IEnumerable
IList
的支持。@xcoder37即使不支持索引器,
ArraySegment
具有类似的概念。