0 based arrays in C # with traditional array syntax []?

I would like to be able to create an array in C # with an arbitrary range of indices, for example an array of 16 elements with indices 100-115.

Native arrays in C # are 0-based, but I am told (for example in a Luaan comment here ) that the C # Array class allows arbitrary lower and upper bounds. But in the examples I've seen, the elements in the Array class are accessible via myArray.GetValue () and myArray.SetValue () instead of the usual array syntax like myArray [ foo ] .

Array arr = Array.CreateInstance(typeof(string), new[]{16}, new[]{100});
Console.WriteLine(arr.Length); // 16
arr.SetValue("foo", 100);
Console.WriteLine(arr.GetValue(100)); // foo

      

Is there a way to make an array with some arbitrary starting index like [100] that I can get using the traditional [] syntax in C #?

+3


source to share


5 answers


You can create a class that implements the decorator pattern: just implement the IList interface (which is also implemented by Array) and make any change you want to that property [int index].



The decorator pattern is described here: http://www.codeproject.com/Articles/479635/UnderstandingplusandplusImplementingplusDecoratorp

+2


source


The Array class does not support this, but you can write your own array class using single radix indices:

public class OneBasedArray<T>
{
    public T[] InnerArray;
    public T this[int i]
    {
        get { return InnerArray[i-1]; }
        set { InnerArray[i-1] = value; }
    }
}

      

And then use it like this:



var myArray = new OneBasedArray<int> { InnerArray = new int[]{ 1, 2, 3, 4, 5 } };
for(int i = 1; i <=5; i++)
{
    Console.WriteLine(myArray[i]);
}

      

This code is just to get the idea, such a class certainly needs a better interface.

+2


source


You can only use an array index if it is at index 0.

You can use an indexer on a custom, non-array, type and use whatever logic you want for it, like making it non-zero indexed, but that's not an option for arrays.

+1


source


I think Lucas's answer is probably the easiest way to deal with this, but if for some reason you really wanted to use Array.CreateInstance

(don't know why you - maybe some external library could insist on this?), you can wrap it in a class like this:

public class NonZeroArray<T>
{
    private readonly Array array;

    public T this[int i]
    {
        get { return (T)array.GetValue(i); }
        set { array.SetValue(value, i); }
    }

    public NonZeroArray(int length, int lowerBounds = 0)
    {
        array = Array.CreateInstance(typeof(T), new int[] { length}, new int[] { lowerBounds } );
    }
}

      

You could obviously make it that much nicer (and work with it) if he implemented the rest IList<T>

. And if you really want your own array, you can implement a property with a getter to expose it when needed.

Using this would be simple:

var myNonZeroArray = new NonZeroArray<string>(16,100);
myNonZeroArray[100] = "foo";
Console.WriteLine(myNonZeroArray[100]);   // prints "foo"

      

+1


source


Here's a custom class that extends IList<T>

to provide functionality to run at a non-zero index:

public class NonZeroList<T> : IList<T>
{
    private int startIndex;
    private List<T> inner;

    public NonZeroList(int startIndex, IEnumerable<T> content)
    {
        this.startIndex = startIndex;
        inner = content.ToList();
    }
    public NonZeroList(int startIndex)
    {
        this.startIndex = startIndex;
        inner = new List<T>();
    }

    public T this[int i]
    {
        get
        {
            return inner[i - startIndex];
        }
        set
        {
            inner[i - startIndex] = value;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach (T i in inner)
            yield return i;
        yield break;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return inner.GetEnumerator();
    }

    public int IndexOf(T item)
    {
        return inner.IndexOf(item) + startIndex;
    }

    public void Insert(int index, T item)
    {
        inner.Insert(index - startIndex, item);
    }

    public void RemoveAt(int index)
    {
        inner.RemoveAt(index - startIndex);
    }

    public void Add(T item)
    {
        inner.Add(item);
    }

    public void Clear()
    {
        inner.Clear();
    }

    public bool Contains(T item)
    {
        return inner.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        inner.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return inner.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return inner.Remove(item);
    }
}

      

To use it, you initialize it in the same way as normal List<T>

, but with a specified start pointer (for example NonZeroList<int> myList = new NonZeroList<int>(20) { 0, 1, 2, 3 };

). Then you can use it just like normal List<T>

or T[]

.

If you want to use it as an array instead of a list, you can just add bounds checking, or implement IEnumerable<T>

instead IList<T>

and create utility functions yourself.

0


source







All Articles