views:

117

answers:

5

Hey

I have an array of MyType s in an object similar to the setup below, I want to be able to set the value of an index on myObject as it is, I cannot change the declaration of MyFunction.

/*...*/
MyType [] myTypedArray = new MyType[100];
MyFunction(myTypedArray);
/*...*/

function MyFunction(object myObject)
{
    myObject[0] = new MyType();
}

This, obviously, doesn't work but I cannot figure out how to get it to work. I cannot cannot use templates/generics it has to be all using reflection.

Note that I have to have myObjectArray, initially, as an "object" as this is how I receive it. I cannot do the initial cast to a object[]. I have tried casting myObjectArray to object[] and it doesn't work.

I also do not have access to MyType as a static type, only runtime.

Any advice would be great, thanks.

+1  A: 

Try something like:

DayOfWeek[] myTypedArray = Enum.GetValues(typeof(DayOfWeek))
                               .OfType<DayOfWeek>().ToArray();
object myObject = myTypedArray;

object[] myObjectArray =   // from object to object[]
        (myObject as Array ?? new object[0]).OfType<object>().ToArray();

Type type = myObjectArray[0].GetType(); // unbox type
myObjectArray[0] = Activator.CreateInstance(type); // create another instance

Note you'll lose type safety.

Rubens Farias
+4  A: 

Declare myObjectArray as an array of objects:

object[] myObjectArray = myTypedArray;
myObjectArray[0] = new MyType(); // okay to go!

Alternatively, if for some reason myObjectArray must be an object you can say:

((object[])myObjectArray)[0] = new MyType();

These are smelly though. And beware of array covariance in C#!

Here's an implementation along the lines that you seem to be looking for:

void AddToArray(object array, int index) {
    if(array == null) {
        throw new ArgumentNullException();
    }
    Type arrayType = array.GetType();
    if(!arrayType.IsArray) {
        throw new InvalidOperationException("array must be an Array");
    }

    (Array)asArray = (Array)array;
    if (index < 0 || index >= asArray.Length) {
        throw new ArgumentOutOfRangeException("index");
    }
    object newInstance = Activator.CreateInstance(elementType);
    asArray.SetValue(newInstance, index);
}

Invoke as:

AddToArray(myObjectArray, 0);

This assumes that elementType has a parameterless constructor. There are ways around this, but this should be enough to get you started. This method also probably needs a better name.

Again, this code is very smelly. I would suggest taking a step back and seeing if you can solve your problem using strongly-typed code.

Jason
I have clarified question, I have no control over how I originally see myObjectArray - it comes in as an object not an object[]
Chris
@Chris: See comment beginning with "Alternatively, if for some reason...".
Jason
Thanks Jason. However I tried something similar and I got an error "Unable to cast object of type 'System.Boolean[]' to type 'System.Object[]'."
Chris
@Chris: Yeah, that's because `bool` is a value type. The CLR will never let you cast an array where the elements are value types to any other array type. So `string[] strings = new string[n]; object o = strings; object[] array = (object[])o;` is legal but `bool[] bools = new bool[n]; object o = bools; object[] array = (object[])o;` is not.
Jason
Any idea what I can do then? The array type could be anything? (Note this is for my own serialization stuff)
Chris
Yes, I will provide an edit.
Jason
You can use the Array.SetValue method directly, rather than casting to object[] (see my response below). This will work for all arrays, including ones of value types
thecoop
A: 

In this case, you need a cast to object[]:

((object[])myObjectArray)[0] = new MyType();
bruno conde
OP says he can't cast to object[]
Rune FS
+1  A: 

You can cast the object to an Array and call SetValue on it, for a completely non-object-specific way of doing it. This'll box & unbox value types as appropriate & do all the necessary array type checking.

thecoop
Thanks this worked perfectly!!
Chris
A: 

((MyType[])myObjectArray)[0] = new MyType(); perhaps?

erikkallen