tags:

views:

553

answers:

4

Although perhaps a bizare thing to want to do, I need to create an Array in .Net with a lower bound > 0. This at first seems to be possible, using:

Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});

Produces the desired results (an array of objects with a lower bound set to 9). However the created array instance can no longer be passed to other methods expecting Object[] giving me an error saying that:

System.Object[*] can not be cast into a System.Object[]. What is this difference in array types and how can I overcome this?

Edit: test code =

Object x = Array.CreateInstance(typeof(Object), new int[] {2}, new int[] {9});
Object[] y = (Object[])x;

Which fails with: "Unable to cast object of type 'System.Object[*]' to type 'System.Object[]'."

I would also like to note that this approach DOES work when using multiple dimensions:

Object x = Array.CreateInstance(typeof(Object), new int[] {2,2}, new int[] {9,9});
Object[,] y = (Object[,])x;

Which works fine.

+1  A: 

I'm not sure about why that can't be passed as Object[], but wouldn't be easy if you just create a real class to wrap an array and handle your "weird logic" in there?

You'd get the benefits of using a real reference object were you could add "intelligence" to your class.

Edit: How are you casting your Array, could you post some more code? Thanks.

Martín Marconcini
It would be nice to wrap, but for certain reasons and in certain circumstances it needs to be avoided. I will edit with more code.
DAC
+2  A: 

This article explains it: http://www.panopticoncentral.net/articles/950.aspx

ionut bizau
+2  A: 

The reason why you can't cast from one to the other is that this is evil.

Lets say you create an array of object[5..9] and you pass it to a function F as an object[].

How would the function knows that this is a 5..9 ? F is expecting a general array but it's getting a constrained one. You could say it's possible for it to know, but this is still unexpected and people don't want to make all sort of boundary checks everytime they want to use a simple array.

An array is the simplest structure in programming, making it too complicated makes it unsusable. You probably need another structure.

What you chould do is a class that is a constrained collection that mimics the behaviour you want. That way, all users of that class will know what to expect.

class ConstrainedArray<T> : IEnumerable<T> where T : new()
{
    public ConstrainedArray(int min, int max)
    {
        array = new T[max - min];
    }

    public T this [int index]
    {
        get { return array[index - Min]; }
        set { array[index - Min] = value; }
    }

    public int Min {get; private set;}
    public int Max {get; private set;}

    T[] array;

    public IEnumerator<T> GetEnumerator()
    {
        return array.GetEnumarator();
    }

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

}
Coincoin
Thanks for the code snippet, but I wish to avoid any type of wrapping when necessary, as this problem arises from a VB6 migration issue, where large amounts of code expect lower bounds > 0. Therefore I am doing my best to determine first if it is possible to NOT use a custom class.
DAC
A: 

Just store your lower bound in a const offset integer, and subtract that value from whatever your source returns as the index.

Also: this is an old VB6 feature. I think there might be an attribute to help support it.

Joel Coehoorn