2010-11-03 48 views
111

Es probable que se trate de una pregunta de principiante, pero sorprendentemente, Google no proporcionó una respuesta.El valor del tipo 'T' no se puede convertir a

que tienen este método bastante artificial

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

     return t; 
    } 

Viniendo de experiencia en C++ He esperado esto funcione. Sin embargo, no compila con "No se puede convertir implícitamente el tipo 'T' a la cadena" y "No se puede convertir el tipo 'T' a la cadena" para las dos asignaciones anteriores.

Estoy haciendo algo conceptualmente incorrecto o simplemente tengo una sintaxis incorrecta. Por favor, ayúdame a resolverlo.

¡Gracias!

+14

OMI, si usted está comprobando tipos genéricos en el código, a continuación, los genéricos, probablemente no son la solución correcta a su problema. –

+0

La expresión 'typeof (T) == typeof (string)' se resuelve en tiempo de ejecución, no en tiempo de compilación. Por lo tanto, la siguiente línea en el bloque no es válida. –

+6

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

Respuesta

218

Aunque está dentro de un bloque if, el compilador no sabe que T es string.
Por lo tanto, no te deja lanzar. (Por la misma razón que no se puede echar a DateTimestring)

Es necesario para echar a object, (que cualquier T pueden transmitir contenido a), y de allí a string (ya object puede ser echado a string).
Por ejemplo:

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

Esto funciona! Supongo que el segundo también debería ser T newT2 = (T) (objeto) t; aunque eso no es un op. – Alex

+2

Adición: las plantillas de C++ son esencialmente cortadas y pegadas en tiempo de compilación con los valores correctos sustituidos. En C#, la plantilla genérica real (no una "instanciación" de la misma) existe después de la compilación y, por lo tanto, debe (perdón por el juego de palabras) ser genérica en los límites de tipo especificados. –

+0

(cadena) (objeto) t; no hace nada aquí, podría dejarlo fuera, el (cadena) (objeto) que es – Doggett

8

Ambas líneas tienen el mismo problema

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

El compilador no sabe que T es una cadena y por lo tanto no tiene manera de saber cómo asignar eso. Pero ya que está marcado puede simplemente forzar con

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

que no es necesario para emitir la camiseta ya que es ya una cadena, también hay que añadir la restricción

where T : class 
+2

Wrong. Esto no compilará Ver mi respuesta – SLaks

+1

Compila muy bien (con el lugar donde está, agregado que unos segundos después de publicado, podría haber pasado por alto). Vaya, nm se olvidó de cambiar el modelo – Doggett

1

Si eres buscando tipos explícitos, ¿por qué declaras esas variables como 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 segunda línea crea una variable de tipo 'T'. – SLaks

+0

Pregunta por qué verificar el tipo? Supongamos que tiene un tipo de campo base que almacena valores 'object', con tipos derivados que almacenan valores' string'. Supongamos que estos campos también tienen un valor "DefaultIfNotProvided", por lo que debe verificar si el valor proporcionado por el usuario (que podría ser un objeto o una cadena o incluso una primitiva numérica) es equivalente a 'default (T)'. La cadena se puede tratar como un caso especial en el que una cadena vacía/en blanco se trata igual que la predeterminada (T), por lo que es posible que desee comprobar si 'T userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace (userValue as string); '. – Triynko

-2

cambiar esta línea:

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

Para esta línea:

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

son lo mismo – bigworld12

0

También recibirá este error si tiene una declaración genérica tanto para su clase y su método. Por ejemplo, el código que se muestra a continuación proporciona este error de compilación.

public class Foo <T> { 

    T var; 

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

} 

Este código se compila (NOTA T retirado de declaración de método):

public class Foo <T> { 

    T var; 

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

} 
Cuestiones relacionadas