如何从C#中的现有数组中获取子数组而无需复制?
我的问题与之类似,尽管在我的案例中有一点不同的概念非常重要——我不能使用内存复制 假设我有10000个元素的数组如何从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
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
具有类似的概念。