2010-11-03 23 views
111

Questa è probabilmente una domanda per principianti, ma a sorpresa Google non ha fornito una risposta.Il valore del tipo "T" non può essere convertito in

ho questo metodo piuttosto artificiale

T HowToCast<T>(T t) 
    { 
     if (typeof(T) == typeof(string)) 
     { 
      T newT1 = "some text"; 
      T newT2 = (string)t; 
     } 

     return t; 
    } 

Provenendo da un C++ sfondo Ho aspettato questo lavoro. Tuttavia, non riesce a compilare con "Impossibile convertire in modo implicito il tipo 'T' in stringa" e "Impossibile convertire il tipo 'T' in stringa" per entrambi i compiti sopra indicati.

Sto facendo qualcosa di concettualmente sbagliato o ho solo la sintassi sbagliata. Per favore aiutami a sistemare questo fuori.

Grazie!

+14

IMO, se si sta controllando i tipi nel codice farmaci generici, quindi generici probabilmente non sono la soluzione giusta per la vostra problema. –

+0

L'espressione 'typeof (T) == typeof (stringa)' viene risolta in fase di runtime, non in fase di compilazione. Quindi la seguente riga nel blocco non è valida. –

+6

(T) Converti.ChangeType (newT1, typeof (T)) – vsapiha

risposta

218

Anche se si trova all'interno di un blocco if, il compilatore non sa che T è string.
Pertanto, non ti consente di trasmettere. (Per la stessa ragione per cui non si può lanciare DateTime-string)

È necessario lanciare a object, (che qualsiasi T può lanciare a), e da lì a string (dal object può essere gettato a string).
Ad esempio:

T newT1 = (T)(object)"some text"; 
string newT2 = (string)(object)t; 
+2

Funziona! Sto indovinando il secondo come dovrebbe essere anche T newT2 = (T) (oggetto) t; anche se questo è un no op. – Alex

+2

Aggiunta: i modelli C++ sono essenzialmente copia e incolla in fase di compilazione con i valori corretti sostituiti. In C# il modello generico attuale (non una "istanza" di esso) esiste dopo la compilazione e quindi deve (perdonare il gioco di parole) essere generico attraverso i limiti del tipo specificato. –

+0

(stringa) (oggetto) t; non fa nulla qui però, potrebbe pure lasciarlo fuori, la (stringa) (oggetto) che è – Doggett

8

Entrambe le linee hanno lo stesso problema

T newT1 = "some text"; 
T newT2 = (string)t; 

Il compilatore non sa che T è una stringa e quindi non ha alcun modo di sapere come assegnare questo. Ma dal momento che è stata selezionata si può solo forzarlo con

T newT1 = "some text" as T; 
T newT2 = t; 

non è necessario per lanciare l't dal momento che è già una stringa, anche bisogno di aggiungere il vincolo

where T : class 
+2

Wrong. Questo non verrà compilato. Vedi la mia risposta. – SLaks

+1

Compila bene (con il punto in cui si trova, aggiunto che pochi secondi dopo l'invio, potrebbe averlo perso). Oops nm ha dimenticato di cambiare il cast – Doggett

1

Se sei controllando i tipi espliciti, perché stai dichiarando quelle variabili come T?

T HowToCast<T>(T t) 
{ 
    if (typeof(T) == typeof(string)) 
    { 
     var newT1 = "some text"; 
     var newT2 = t; //this builds but I'm not sure what it does under the hood. 
     var newT3 = t.ToString(); //for sure the string you want. 
    } 

    return t; 
} 
+4

La seconda riga crea una variabile di tipo 'T'. – SLaks

+0

Chiedete perché controllare il tipo? Supponiamo di avere un tipo di campo base che memorizza i valori di 'object', con tipi derivati ​​che memorizzano i valori' stringa'. Supponiamo che questi campi abbiano anche un valore "DefaultIfNotProvided", quindi è necessario verificare se il valore fornito dall'utente (che potrebbe essere un oggetto o una stringa o anche una primitiva numerica) è equivalente a "default (T)". La stringa può essere trattata come un caso speciale in cui una stringa vuota/spazio vuoto viene considerata uguale a quella predefinita (T), quindi è consigliabile verificare se 'T userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace (userValue as string); '. – Triynko

-2

Modifica questa linea:

if (typeof(T) == typeof(string)) 

Per questa linea:

if (t.GetType() == typeof(string)) 
+1

sono gli stessi – bigworld12

0

Si riceverà anche questo errore se si dispone di una dichiarazione generica sia per la classe e il metodo. Ad esempio il codice mostrato di seguito dà questo errore di compilazione.

public class Foo <T> { 

    T var; 

    public <T> void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException { 
     this.var = cls.newInstance(); 
    } 

} 

Questo codice si compila (Nota T rimossa dalla dichiarazione di metodo):

public class Foo <T> { 

    T var; 

    public void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException { 
     this.var = cls.newInstance(); 
    } 

} 
Problemi correlati