Why can't I convert an object (which is really object[]) to string[]?

12,876

Solution 1

string[] newarr =  Array.ConvertAll(objects, s => (string)s);

--EDIT--

since you've said I have an object (knowing that it is an object[] actually)

string[] newarr =  Array.ConvertAll((object[])objects, s => (string)s);

Solution 2

This is a particularly confusing feature of C#. Here's the deal.

Throughout this discussion we assume that the element type of an array is a reference type, not a value type.

C# supports unsafe array covariance. That means that if you have an array of string, you can convert it to an array of object, because a string can be converted to an object:

string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal

If you then try to get an element out of a2, it works:

object o3 = a2[0]; 

That's legal because a2[0] is really a1[0], which is a string, which is convertible to object.

However, if you attempt to write to the array then you'll get an error at runtime:

a2[0] = new object();

This fails at runtime because a2 is really an array of strings, and you can't put a non-string into an array of strings.

So C# is already horribly broken; it is possible to write a program that compiles and looks normal but suddenly crashes with a type exception at runtime because you tried to put an object into an array of objects that is not actually an array of objects.

The feature you want is even more broken than that, and thank goodness C# does not support it. The feature you want is:

object[] a4 = { "Hello" };
string[] a5 = a4; 

That would be unsafe array contravariance. It breaks horribly like this:

a4[0] = new Customer(); // Perfectly legal 
string s6 = a5[0]; 

And now we just copied a Customer into a variable of type string.

You should avoid any kind of array covariance or contravariance; array contravariance is, as you've discovered, not legal, and array covariance is making little time bombs in your program that go off unexpectedly. Make your arrays of the right type to begin with.

Share:
12,876
leora
Author by

leora

Updated on July 26, 2022

Comments

  • leora
    leora almost 2 years

    I have a field that is of type 'object'. When I inspect it within the Watch window of visual studio I see its Object[] and when I drill into the elements I see each element is a string.

    But when I try to cast this to a String[] I get this error:

    Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]

    Any reason why I can't do this cast? What is the best way to convert this object to a string array?

  • leora
    leora about 12 years
    i don't have object[] . .i only have object . . given that I get "Can't resolve Cast"
  • leora
    leora about 12 years
    this doesn't seem to compile . . i am getting error: Type inference cannot be inferred . . .
  • Arion
    Arion about 12 years
    I changed the type for you. Test again
  • leora
    leora about 12 years
    hmm . . for some reason your solution is the only one that compiles and works for me . .
  • Servy
    Servy about 12 years
    @leora Most everyone else solved a portion of the problem, but not the whole thing. They solved that portion more cleanly/elegantly. As I said, this code is designed to show you what needs to happen, even if there is a library method that does half of it for you.
  • L.B
    L.B about 12 years
    @Servy but not the whole thing are you sure?.
  • Servy
    Servy about 12 years
    @L.B You fixed yours on edit. At first you didn't (i.e. at the time of my post.) Every other answer still hasn't included the relevant cast from object to object[].
  • kvb
    kvb about 12 years
    I agree with most of what you say, but I disagree that array contravariance is even more broken than array covariance - they seem like perfectly dual situations. With array contravariance, you could read and write to the object array, write to the string array, and read from the string array as long as an object of a different type wasn't written to that location through the object array. With covariance, you could read and write to the string array, read from the object array, and write to the object array as long as you're inserting a string in that location.
  • Eric Lippert
    Eric Lippert about 12 years
    @kvb: I take your point. I say that it is "even more broken" because in the covariant case, the broken scenario is: conversion-followed-by-write fails. But since many people use arrays as effectively read-only arrays -- they only write when the array is created -- there is no conversion-followed-by-write, there is only conversion followed by read. That is, it can only break if there was a write following the conversion. But the contravariant case can break on any read after the conversion; the array might not have been all strings to begin with!