在C#中引用数组的一部分

我有一个包含一些数据的数组,比如标题和真实数据。 我需要将数组中包含的数据传递给方法,但我绝对想避免将其复制到另一个数组。

我想到了像ArraySegment这样的东西,但似乎在我的情况下不起作用(或者我错了?)。

那么,如何将数组的一部分传递给方法,因为它本身就是一个数组?

谢谢您的回复!

干杯

跳过并采取 :

 var subArray = array.Skip(5).Take(10); 

如果你想坚持只是基本数组 (即int []数字),那么最有效的方法是让你的函数直接获取偏移/计数

有很多IOfunction可以做类似的事情:

 readData(data, 0, 4); string readData(byte [] buffer, int offset, int length) 

另一种选择是使用IEnumberable 并使用skip / take

 readData(data.Skip(0).Take(4)); string readData(IEnumerable buffer) 

重要的是要记住,在c#中你没有处理指针 ,你正在处理对象。

我有与Jon Skeet完全相同的想法:在T[]周围实现一个包装器,它通过索引提供随机访问,自动处理索引访问的调整。

我刚刚将快速实现集中在一起(跳过这个答案的底部进行简短的演示):

 public struct ArrayFragment : IList { private T[] _source; private int _start; private int _count; public ArrayFragment(T[] source, int start, int count) { if (source == null) { throw new ArgumentNullException("source"); } if (start < 0 || start >= source.Length) { throw new ArgumentOutOfRangeException("start"); } if (count > source.Length - start) { throw new ArgumentOutOfRangeException("count"); } _source = source; _start = start; _count = count; } public T this[int index] { get { return _source[_start + index]; } } public int Count { get { return _count; } } public bool Contains(T value) { int index = Array.IndexOf(_source, value, _start, _count); return index != -1; } public void CopyTo(T[] destination, int index) { Array.Copy(_source, _start, destination, index, _count); } public int IndexOf(T value) { int index = Array.IndexOf(_source, value, _start, _count); return index != -1 ? index - _start : -1; } public IEnumerator GetEnumerator() { for (int i = 0; i < _count; ++i) { yield return _source[_start + i]; } } #region Explicit Interface Implementation // a bunch of explicitly implemented IList members // that all throw a NotSupportedException #endregion } 

这是一个演示:

 int[] numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; try { var fragment = new ArrayFragment(numbers, 2, 5); Console.WriteLine("Iterating using foreach: "); foreach (int number in fragment) { Console.WriteLine(number); } Console.WriteLine("Iterating using for: "); for (int i = 0; i < fragment.Count; ++i) { Console.WriteLine(fragment[i]); } Console.WriteLine("Index of 4: {0}", fragment.IndexOf(4)); Console.WriteLine("Index of 1: {0}", fragment.IndexOf(1)); Console.WriteLine("Index of 9: {0}", fragment.IndexOf(9)); Console.WriteLine("Index of 7: {0}", fragment.IndexOf(7)); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadLine(); 

输出:

使用foreach迭代:
 3
 4
五
 6
 7
迭代使用:
 3
 4
五
 6
 7
指数为4:1
指数为1:-1
指数9:-1
指数7:4

从我所看到的,你有两个选择:

  1. 修改您正在调用的方法(如果您有选项)。 您可以让它接受一个数组,一个起始索引和一个结束索引,而不仅仅是接受一个数组(或IEnumerable)。

  2. 传入一个IEnumerable对象,而不是传递数组,该对象枚举数组中所需的范围(不需要复制数组中的项)。 一种方法是:

 var slice = someArray.Skip(startIndex).Take(endIndex - startIndex); 

一种选择是在以不可变的方式实现IList方面实现类似 ReadOnlyCollection东西,但在现有集合上将其公开为“视图”,适当地转移任何索引访问(并使用适当的计数等) 。

它可能是一个非常方便的包装类。 然后,您将修改您的方法以接受适当的IList而不是数组。