2012-04-13 11 views
8

Ho un campo che è di tipo 'oggetto'. Quando lo controllo all'interno della finestra di controllo dello studio visivo, vedo il suo oggetto [] e quando eseguo il drill sugli elementi vedo che ogni elemento è una stringa.Perché non posso convertire un oggetto (che è veramente oggetto []) in stringa []?

Ma quando provo a lanciare questa in una stringa [] ottengo questo errore:

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

Qual è il motivo per cui non posso fare questo cast? Qual è il modo migliore per convertire questo oggetto in un array di stringhe?

+0

Come stai trasmettendo il tuo array? Nel complesso? È necessario eseguire il cast di ogni elemento dell'array singolarmente. – Msonic

+0

Sì, lo sta chiaramente rilasciando nel suo insieme. –

+1

La varianza della matrice di riferimento è l'altro modo; puoi lanciare qualcosa che è ** in realtà ** un 'string []' come un 'oggetto []', ma per andare nell'altro modo deve essere effettivamente una 'stringa []' –

risposta

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

--EDIT--

visto che hai detto Ho un object (sapendo che si tratta di una realtà object[])

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

questo non sembra essere compilato. . sto ricevendo errore: l'inferenza di tipo non può essere dedotta. . . – leora

+0

@leora vedere la risposta aggiornata. –

-1

È possibile convertire il verastring[] a object[].

Questo è un Array covariance

riesci a trovare un chiaro esempio di collegamento.

+0

@downvoter: cura di spiegare? – Tigran

+0

non è il mio d/v ma forse b/c non hai incluso un esempio –

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]; 
} 

Altre risposte qui ti mostrano modi più rapidi/brevi per eseguire la conversione. Ho scritto il tutto in questo modo perché mostra cosa sta realmente succedendo e cosa deve accadere. Dovresti utilizzare uno dei metodi più semplici nel tuo codice di produzione attuale.

+0

hmm. . per qualche ragione la tua soluzione è l'unica che compila e lavora per me. . – leora

+0

@leora Quasi tutti gli altri hanno risolto una parte del problema, ma non il tutto. Hanno risolto quella parte in modo più pulito/elegante. Come ho detto, questo codice è progettato per mostrare ciò che deve accadere, anche se esiste un metodo di libreria che ne fa la metà. – Servy

+0

@Servy 'ma non il tutto 'ne sei sicuro ?. –

-1

È necessario trasmettere ogni elemento della raccolta e non la raccolta stessa.

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

Non ho oggetto []. . Ho solo oggetti . dato che ottengo "Impossibile risolvere Cast" – leora

+0

@leora 'utilizzando System.Linq;' –

+0

hmm. . . ho già questo riferimento . . – leora

23

Questa è una caratteristica particolarmente confuso di C#. Ecco l'accordo.

In questa discussione si assume che il tipo di elemento di un array sia un tipo di riferimento, non un tipo di valore.

C# supporta covarianza di matrice non sicura. Ciò significa che se si dispone di una vasta gamma di stringa, è possibile convertirlo in un array di oggetti, perché una stringa può essere convertito in un oggetto:

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

Se quindi si tenta di ottenere un elemento di a2, funziona:

object o3 = a2[0]; 

Questo è legale perché a2[0] è davvero a1[0], che è una stringa, che è convertibile in oggetto.

Tuttavia, se si tenta di scrivere alla matrice, allora si otterrà un errore in fase di esecuzione :

a2[0] = new object(); 

questo non riesce in fase di esecuzione perché a2 è davvero un array di stringhe, e non puoi mettere una non stringa in una serie di stringhe.

Quindi C# è già orribilmente rotto; è possibile scrivere un programma che si compila e sembra normale ma si blocca improvvisamente con un'eccezione di tipo in fase di esecuzione perché si è tentato di inserire un oggetto in una matrice di oggetti che in realtà non è una matrice di oggetti.

La funzione desiderata è ancora più difettosa di quella, e grazie a Dio C# non la supporta. La funzione che si desidera è:

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

Sarebbe pericoloso serie controvarianza. Si rompe orribilmente simile a questo:

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

E ora abbiamo appena copiato un clienti in una variabile di tipo stringa .

È necessario evitare qualsiasi tipo di covarianza o controvariante dell'array; La contravarianza dell'array è, come hai scoperto, non legale, e la covarianza dell'array sta facendo delle piccole bombe a orologeria nel tuo programma che esplodono inaspettatamente. Crea gli array del tipo giusto per iniziare.

+1

Sono d'accordo con la maggior parte di quello che dici, ma non sono d'accordo sul fatto che la contravarianza dell'array sia ancora più rara della covarianza dell'array - sembrano situazioni perfettamente duali. Con la contravarianza dell'array, è possibile leggere e scrivere sull'array di oggetti, scrivere nell'array di stringhe e leggere dall'array di stringhe finché un oggetto di un tipo diverso non è stato scritto in tale posizione attraverso l'array di oggetti. Con covarianza, è possibile leggere e scrivere sull'array di stringhe, leggere dall'array di oggetti e scrivere sull'array di oggetti finché si inserisce una stringa in tale posizione. – kvb

+4

@kvb: Prendo il tuo punto. Dico che è "ancora più rotto" perché nel caso covariante, lo scenario infranto è: conversione-seguita-da-scrittura fallisce. Ma dal momento che molte persone usano gli array come * effettivamente * array di sola lettura - scrivono solo quando viene creato l'array - non c'è conversione - seguita da scrittura, c'è solo conversione seguita da lettura. Cioè, può * solo * interrompere se c'è stata una * scrittura * dopo la conversione. Ma il caso controvariante può rompere * qualsiasi * letto dopo la conversione; la matrice potrebbe non essere stata tutte le stringhe per cominciare! –

0

La regola di programmazione orientata agli oggetti è -

"classe derivata può sempre essere di tipo colato alla classe di base" e "una classe base può essere colato per classe derivata solo se l'istanza corrente che classe di base stretta è in realtà la classe derivata "

es. (A è base e B è derivato)

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

illegale:>

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

Stessa cosa si applica a Object e le classi String. L'oggetto è una classe base e la stringa è una classe derivata.

Problemi correlati