2012-08-08 10 views
6

Estoy escribiendo un método para hacer una conversión de tipo inteligente - usando ToString() si el parámetro de tipo pasa a ser una cadena, de lo contrario lanzando pero devolviendo nulo si el molde no lo hace trabajo. Básicamente obtiene tanta información de v que puede sin lanzar una excepción.Casting cadena de tipo genérico que es una cadena

puedo comprobar que el T es de hecho un string antes de intentar el reparto, pero el compilador todavía no es un fan:

Cannot convert type 'string' to 'T' 

Y aquí es mi método:

public T? Convert<T>(object v) 
{ 
    if (typeof(T) == typeof(string)) { 
    return (T)v.ToString(); // Cannot convert type 'string' to 'T' 
    } else try { 
     return (T)v; 
    } catch (InvalidCastException) { 
    return null; 
    } 
} 

también quisiera saber si esto es algún tipo de pecado imperdonable. Lo estoy usando para tratar con algunas estructuras de datos que podrían tener tipos mixtos.

+0

Hay otros problemas. Su método no puede tener el tipo de retorno 'T?' Cuando no hay restricción en 'T'. Por ejemplo, no hay nada llamado '¿cadena?' Porque la cadena es un tipo de referencia. –

Respuesta

25

Es, básicamente, tiene que ir a través de object cuando se lanza a un tipo genérico:

return (T)(object) v.ToString() 

y

return (T)(object) v; 

Yo usaría is en lugar de atrapar un InvalidCastException sin embargo.

Consulte Eric Lippert's recent blog post para obtener más información sobre por qué es necesario.

En particular:

Debido a que el compilador sabe que la única manera esta conversión podría tener éxito si es U es bool, pero U puede ser cualquier cosa! El compilador asume que la mayoría de las veces U no se construirá con bool, y por lo tanto, este código es casi seguro un error, y el compilador le está señalando ese hecho a su atención.

(Sustituto T para U y string para bool ...)

+1

¿No sería la mejor opción? –

+1

@SteveCzetty: No sabemos que 'T' sea un tipo anulable, por lo que' as' no funcionaría (IIRC). –

+0

Buen punto. Aunque tampoco creo que 'is' vaya a funcionar, a menos que' T' esté restringido a 'clase'. (IIRC, también) –

2

Es necesario para emitir su cadena como object como su tipo de retorno es decir genérica

return (T)(object)v.ToString(); 
+1

Eso no es boxeo. No hay tipos de valores involucrados. –

+0

@JonSkeet ¡Sí, usó la palabra incorrecta! Quería decir lanzar ... – James

0

tratar de convertir a object antes de convertirse al T

return (T)(object)v; 
0
using System.ComponentModel; 

...

public T Convert<T>(object v) { 
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(v); 
} 

Advertencia, esto generará una excepción si no existe una conversión entre T y el objeto contenido en v.

Cuestiones relacionadas