2

I have a generic argument T which is an array in one particular case. Is it possible to cast array of objects to the array of typeof(T).GetElementType()? For example:

public TResult Execute<TResult>()// MyClass[] in this particular case
{
    var myArray = new List<object>() { ... }; //actual type of those objects is MyClass
    Type entityType = typeof(TResult).GetElementType(); //MyClass
    //casting to myArray to array of entityType 
    TResult result = ...;
    return result;    
} 
2
  • Thank you for your replies, but the problem is that Execute method it's an implementation of the interface and I can't change its signature or add a new one. Commented Aug 23, 2016 at 8:24
  • See edits to my answer Commented Aug 23, 2016 at 8:50

3 Answers 3

3

This is not a good idea. You have no way to constrain TResult to an array, so with your current code, someone could call Excute<int> and get a runtime exception, yuck!

But, why constrain to an array to begin with? Just let the generic parameter be the type of the element itself:

public TResult[] Execute<TResult>()
{
    var myArray = ... 
    return myArray.Cast<TResult>().ToArray();
}

UPDATE: In response to your comments:

If Execute is an interface method you can not change, then you can do the following:

public static TResult Execute<TResult>()
{
    var myArray = new List<object>() { ... };
    var entityType = typeof(TResult).GetElementType();
    var outputArray = Array.CreateInstance(entityType, myArray.Count);
    Array.Copy(myArray.ToArray(), outputArray, myArray.Count); //note, this will only work with reference conversions. If user defined cast operators are involved, this method will fail.
    return (TResult)(object)outputArray;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can use the extension methods myArray.Cast<MyClass>().ToArray() to return an array of MyClass.

I think you mean to return TResult[] also:

public TResult[] Execute<TResult>()//MyClass[] in this particular case
{
    return myArray.Cast<MyClass>().ToArray();
}

You will need to add

using System.Linq;

In order to see these methods.

Comments

1

I agree with with InBetween that it's a bad idea, but I don't know your context and why you need this. But you can achieve it like that:

public TResult Execute<TResult>()// MyClass[] in this particular case
{
    var myArray = new List<object>() { ... }; //actual type of those objects is MyClass

    Type genericArgument = typeof(TResult);
    if (!genericArgument.IsArray)
       // what do you want to return now???

    Type elementType = genericArgument.GetElementType();

    MethodInfo cast = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(elementType);
    MethodInfo toarray = typeof(Enumerable).GetMethod("ToArray").MakeGenericMethod(elementType);

    object enumerable = cast.Invoke(null, new object[]{myArray});
    object array = toarray.Invoke(null, new object[]{enumerable});

    return (TResult)array;
}

This uses reflection to get the LINQ extension for the specific generic arguments. The question is: what should this method return if TResult is not an array. There seems to be a design flaw.

2 Comments

Thanks a lot! I've already have an implementation for non-array TResult(it's default case) so everything should work fine
I dont really think it needs to be this involved. The OP is basically asking for reference conversions (object -> realUnderlyingType). In that scenario, you can use Array.Copy. Check out my answer.

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.