Archives

Archives / 2006 / June
  • ArraySegment Structure - what were they thinking?

    From the MSDN docs:
    ArraySegment is a wrapper around an array that delimits a range of elements in that array. Multiple ArraySegment instances can refer to the same original array and can overlap.

    Turns out this structure doesn't even deserve the definition 'wrapper'. It simply takes the array, offset and number of elements in your segment, and sets a few properties accordingly.

    Subsequently when you want to iterate over the items in your ArraySegment, you still need to use a combination of Offset and Count to achieve this. How is this different from not creating an ArraySegment and define your Offset in-situ as well as the number of elements?

    I was expecting to be able to do something like this:

    ArraySegment<string> seg = new ArraySegment<string>(new string[] { "John","Jack","Jill","Joe"},1,2);
    // Access first item in segment
    string first = seg[0];
    // Iterate through ArraySegment
    foreach (string s in seg)
    {
        Console.WriteLine(s);
    }


    Turns out you can't. There's no indexer for ArraySegment and no enumerator. You have to access the .Array property and use .Count and .Offset as passed to the constructor. What is the point of that!?

    So I rolled my own generic DelimitedArray class which does exactly that. See the inline code below.

        public class DelimitedArray<T>
        {
            public DelimitedArray(T[] array, int offset, int count)
            {
                this._array = array;
                this._offset = offset;
                this._count = count;
            }

            private int _offset;
            private T[] _array;

            private int _count;
            public int Count
            {
                get { return this._count; }
            }

            public T this[int index]
            {
                get
                {
                    int idx = this._offset + index;
                    if (idx > this.Count - 1 || idx<0)
                    {
                        throw new IndexOutOfRangeException("Index '" + idx + "' was outside the bounds of the array.");
                    }
                    return this._array[idx];
                }
            }

            public IEnumerator<T> GetEnumerator()
            {
                for (int i = this._offset; i < this._offset + this.Count; i++)
                {
                    yield return this._array[i];
                }
            }
        }


    Hope this is of use to someone.