7

Is there a way in c# to do something like this:

public void Foo<T>()
{
    T[] arr = Goo() as T[];
}

Where Goo returns an object[], Using reflection or whatever?

4
  • I don't think an object[] could ever be a T[]. An object could be though. Commented Sep 24, 2012 at 6:15
  • @Damien_The_Unbeliever: Covariance and Contravariance in C#, Part Two: Array Covariance Commented Sep 24, 2012 at 6:17
  • @Ani - I could be misreading that, but it seems to say that object[] a = new T[] will be valid (where T:class), not the other way around. Commented Sep 24, 2012 at 6:19
  • 1
    @Damien_The_Unbeliever it depends on what the object[] actually is ;p Since T[] can be represented as an object[], it is possible that your object[] is actually a T[]. However, if the array is constructed as an object[] but happens to contain all T, then indeed: the cast will fail. Commented Sep 24, 2012 at 6:47

2 Answers 2

7

You could use LINQ:

public void Foo<T>()
{
    T[] arr = Goo().OfType<T>().ToArray();
}

In your example you are casting the object[] to T[] which will also work if the two types match exactly:

public void Foo<T>()
{
    T[] arr = Goo() as T[];
    if (arr != null)
    {
        // use the array
    }
}

For example this will work in the following case:

public object[] Goo()
{
    return new string[] { "a", "b" };
}

and then calling Foo like this:

Foo<string>();
Sign up to request clarification or add additional context in comments.

Comments

1

Perhaps the simplest and most reliable approach is to copy the array, doing the cast item-by-item:

public void Foo<T>()
{
    T[] arr = Array.ConvertAll(Goo(), x => (T)x);
}

This is an "unbox.any", which means (to the JIT):

  • do a castclass (i.e. reference-preserving type-check) if T turns out to be reference-type
  • do an unbox if T turns out to be value-type

Arrays of reference-types are covariant, meaning that a T[] can be represented as an object[]. Because of this, there is a chance that the result of Goo() is actually a T[]. We might also want to test this:

public T[] Foo<T>()
{
    var tmp = Goo();
    T[] arr = tmp as T[];
    if(arr == null && tmp != null) {
        arr = Array.ConvertAll(Goo(), x => (T)x);
    }
    return arr;
}

One annoyance of this though is that we now have different semantics - in some cases it is the same array, in some cases it is copied. This could be problematic if we mutate the array.

2 Comments

Hmm ... you have void in the signature, yet you return the array? Shouldn't it have a T[] as a return type?
@Nocitus yup; the danger of coding on a 'phone :)

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.