2012-04-13 19 views
8

Tengo un campo que es de tipo 'objeto'. Cuando lo inspecciono dentro de la ventana Inspección de Visual Studio veo su Objeto [] y cuando profundizo en los elementos veo que cada elemento es una cadena.¿Por qué no puedo convertir un objeto (que en realidad es el objeto []) en una cadena []?

Pero cuando intento de echar a un String [] me sale este error:

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

Cualquier razón por la que no puedo hacer este reparto? ¿Cuál es la mejor manera de convertir este objeto a una matriz de cadenas?

+0

¿Cómo está generando su matriz? ¿Como un todo? Necesita lanzar cada elemento de su matriz individualmente. – Msonic

+0

Sí, claramente lo está lanzando como un todo. –

+1

Varianza de matriz de referencia es a la inversa; puedes lanzar algo que es ** en realidad ** a 'string []' como 'object []', pero para ir hacia el otro lado debe ser en realidad una 'cadena []' –

Respuesta

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

--EDIT--

Puesto que usted ha dicho Tengo una object (sabiendo que es una realidad object[])

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

, esto no parece compilarse. . recibo un error: la inferencia de tipo no puede inferirse. . . – leora

+0

@leora ver la respuesta actualizada. –

-1

Se puede convertir el verdadero string[] a object[].

Esta es una Array covariance

se puede encontrar un ejemplo claro en el enlace.

+0

@downvoter: ¿me importa explicarlo? – Tigran

+0

no es mi d/v pero quizás b/c no incluyó un ejemplo –

0
object[] original = new object[]{"1", "2"}; 
//some code in between here 
object obj = original ; 
object[] objArray = (object[])obj; 
string[] newArray = new string[objArray.Length]; 
for(int i = 0; i < newArray; i++) 
{ 
    newArray[i] = (string)objArray[i]; 
} 

Otras respuestas aquí le muestran formas más rápidas/más cortas de realizar la conversión. Escribí todo esto así porque muestra lo que realmente está sucediendo y lo que debe suceder. Debe usar uno de los métodos más simples en su código de producción real.

+0

hmm. . por alguna razón, su solución es la única que compila y funciona para mí. . – leora

+0

@leora La mayoría de los demás resolvió una parte del problema, pero no todo. Solucionaron esa porción más limpia y elegantemente. Como dije, este código está diseñado para mostrarle lo que debe suceder, incluso si hay un método de biblioteca que hace la mitad por usted. – Servy

+0

@Servy 'pero no todo, ¿estás seguro ?. –

-1

Debe moldear cada elemento de la colección y no la colección en sí.

object[] ovalues = new object[] { "alpha", "beta" }; 
string[] svalues = ovalues.Cast<string>().ToArray(); 
+0

No tengo objeto []. .i solo tengo un objeto. . dado que obtengo "No se puede resolver el envío" – leora

+0

@leora 'utilizando System.Linq;' –

+0

hmm. . . ya tengo esa referencia. . . – leora

23

Esta es una característica particularmente confusa de C#. Aquí está el trato.

A lo largo de esta explicación suponemos que el tipo de elemento de una matriz es un tipo de referencia, no un tipo de valor.

C# admite insegura matriz covarianza. Eso significa que si tiene una matriz de cadena, puede convertirlo en una gran variedad de objetos, ya que una cadena se puede convertir en un objeto:

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

Si a continuación, intenta obtener un elemento de a2, funciona:

object o3 = a2[0]; 

Eso es legal porque es realmente a2[0]a1[0], que es una cadena, que es convertible a objetar.

Sin embargo, si se intenta escribir a la matriz entonces obtendrá un error en tiempo de ejecución :

a2[0] = new object(); 

Esta falla en tiempo de ejecución porque a2 es realmente una matriz de cadenas, y no puede poner un no-cadena en una matriz de cadenas.

Así que C# ya está horriblemente roto; es posible escribir un programa que compila y se ve normal, pero de repente falla con una excepción de tipo en el tiempo de ejecución porque trataste de poner un objeto en una matriz de objetos que en realidad no es una matriz de objetos.

La función que desea es aún más rota que la, y gracias a Dios C# no la admite. La función que desea es:

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

Eso sería peligroso arsenal contravarianza. Se rompe horrible como esto:

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

Y ahora que acabamos de copiar un cliente en una variable de tipo cadena .

Debe evitar cualquier tipo de matriz de covarianza o contravarianza; la contravariancia de matriz es, como usted ha descubierto, no legal, y la covarianza de matriz está haciendo pequeñas bombas de tiempo en su programa que se activan inesperadamente. Haga sus matrices del tipo correcto para comenzar.

+1

Estoy de acuerdo con la mayoría de lo que dices, pero estoy en desacuerdo con que la contravariancia de la matriz está incluso más que rota que la covarianza de la matriz; parecen situaciones perfectamente duales. Con la contravariancia de matriz, puede leer y escribir en la matriz de objetos, escribir en la matriz de cadenas y leer desde la matriz de cadenas, siempre que no se haya escrito un objeto de un tipo diferente en esa ubicación a través de la matriz de objetos. Con la covarianza, puede leer y escribir en la matriz de cadenas, leer desde la matriz de objetos y escribir en la matriz de objetos siempre que inserte una cadena en esa ubicación. – kvb

+4

@kvb: Entiendo tu punto. Digo que está "aún más roto" porque en el caso covariante, el escenario roto es: la conversión seguida de la escritura falla. Pero debido a que muchas personas usan matrices como * efectivamente * matrices de solo lectura, solo escriben cuando se crea la matriz, no hay conversión seguida por escritura, solo hay conversión seguida de lectura. Es decir, solo * puede * romperse si hubo una * escritura * después de la conversión. Pero el caso contravariante puede romperse * cualquier * lectura después de la conversión; la matriz podría no haber sido todo para empezar! –

0

La regla en la programación orientada a objetos es -

"clase derivada puede ser siempre tipo fundido a la clase base" y "una clase base puede lanzar a clase derivada sólo si la instancia actual que asimiento clase base off es en realidad clase derivada "

por ej. (A es base y B se deriva)

A a = new B(); // legal; 
B b = (B) a ; // legal as "a" is actually B (in first statement) 

ilegal: se aplica>

A a = new A(); 
B b = (B) a; // not legal as "a" is A only. 

mismo a objeto y clases de Cuerda. El objeto es clase base y la cadena es Clase derivada.

Cuestiones relacionadas