3

I'd like to be able to create an array in C# with an arbitrary range of index bounds, e.g., a 16 element array with indices of 100-115.

Native arrays in C# are 0-based, but I'm told (e.g., in Luaan's comment here), that the C# Array class allows arbitrary lower and upper bounds. But in the examples I've seen elements in the Array class are accessed via myArray.GetValue() and myArray.SetValue() instead of conventional 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 any way to make an array with some arbitrary starting index, like [100] that I can access with traditional [ ] syntax in C#?

10
  • 5
    Are you looking for indexers, or had you already ruled those out somehow? Commented Jul 10, 2015 at 19:33
  • 5
    why do you need this? no offense, but this sounds like a super bad idea. Commented Jul 10, 2015 at 19:42
  • I honestly can't think of a case where you would need to do this... Commented Jul 10, 2015 at 19:44
  • 2
    Will Dictionary<int, string> work for you? After making an instance of it, you can add items like dict.Add(100, "Hello") and access it by dict[100] (gives " Hello"). Commented Jul 10, 2015 at 19:49
  • 1
    @user316117 Lukas is the guy who wrote an answer for you. You really should sub-class all of this. Commented Jul 10, 2015 at 20:05

5 Answers 5

2

You could create a class that implements the decorator pattern: just implement the IList interface (wich is also implemented by Array) and do whatever shifting you want on the this [int index] property.

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

Sign up to request clarification or add additional context in comments.

Comments

2

The Array class does not support this, but you can write your own array class with one-based 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 only to get the idea, such a class would of course need a nicer interface.

Comments

1

You can only use an array's indexer when it's a 0-indexed array.

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

Comments

1

I think Lukas' answer is probably the easiest way to handle this, but if, for some reason, you really wanted to use Array.CreateInstance (not sure why you would - maybe some external library might insist on it?), you could 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 this a lot prettier (and easier to work with) by having it implement the rest of IList<T>. And if you really need the native array, you could implement a property with a getter to expose it when needed.

Using it would be simply:

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

Comments

0

Here's a custom class that extends IList<T> to provide functionality for starting 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 just as you would a normal List<T>, but with the start index specified (e.g. NonZeroList<int> myList = new NonZeroList<int>(20) { 0, 1, 2, 3 };). You can then use it just as you would a normal List<T> or T[].

If you want to use it as an array instead of a list, then you can simply add bounds checking or implement IEnumerable<T> instead of IList<T>, and create utility functions yourself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.