2010-01-22 12 views
5

¿Podría tener algo como esto:Usando métodos genéricos, ¿es posible volver a obtener diferentes tipos del mismo método?

int x = MyMethod<int>(); 
string y = MyMethod<string>(); 

Por lo tanto, un método devolver diferentes tipos en función de T. Por supuesto, no sería lógica dentro del método para asegurarse de que regresaba lo correcto.

Nunca puedo obtener algo así para ejecutar. Se queja de que no se puede convertir el valor devuelto a T:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return 0; 
    } 
    else 
    { 
    return "nothing"; 
    } 
} 
+4

F En primer lugar, este código no se compilará, ya que no hay un tipo de devolución especificado. Supongo que quiere que lea 'T estático en público MyMethod ()' – Nick

+0

Publique eso como su respuesta, Nick. Creo que esa es la solución que él necesita. – JMD

+0

... aunque ese código como está escrito arriba todavía no se compilará, porque "nada" no es T, excepto cuando T es una cadena, y 0 no es T, excepto cuando T es un tipo numérico. – JMD

Respuesta

10

intente lo siguiente

public static T MyMethod<T>() { 
    if (typeof(T) == typeof(Int32)) { 
    return (T)(object)0; 
    } else { 
    return (T)(object)"nothing"; 
    } 
} 

El truco aquí es el casting para object. Lo que intenta hacer es inherentemente inseguro ya que el compilador no puede inferir que 0 o "nada" son convertibles a T. No tiene límites después de todo. Así que simplemente dile al compilador explícitamente que no es seguro con el casting al object.

+0

Esto funciona. Entonces, ¿el único que crees que estás haciendo diferente es arrojarlo a un objeto primero, luego a T? – Deane

+1

Si bien esto resuelve el error de tiempo de compilación, pero aún no tiene sentido. Si T es, por ejemplo, un tipo de página, no tiene sentido devolver un molde de cuerda a T a través de este truco (objeto). La única razón por la que compila es porque las cadenas y los enteros se pueden convertir a objetos, y los objetos pueden ser mayúsculas y minúsculas para sus tipos descendientes (es decir, todo). –

0

Podría hacer, si desea que se devuelva un valor de tipo "nulo" si no es un int. Pero si desea una cadena en todos los demás casos, verifique las otras respuestas.

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return (T)(object)0; 
    } 
    else 
    { 
    return default(T); // or null 
    } 
} 
+0

Para la muestra de cadena, OP quiere que devuelva un valor de cadena específico, no predeterminado (T). También te falta un tipo de devolución. – JaredPar

+0

Verdadero ... y me lo estoy perdiendo porque copié el código y me salté esa parte antes de la edición. –

+0

Esto no funcionará - no hay conversión entre int y T – Lee

0

@Nick es correcto en su comentario que su código no se compilará. Pero suponiendo que decir:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return 0; 
    } 
    else 
    { 
    return "nothing"; 
    } 
} 

Se puede ser difícil de hacer los genéricos no genérico como que está intentando (y realmente contraviene el punto entero), pero esto debería funcionar:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return (T)(object)0; 
    } 
    else if(typeof(T) == typeof(string)) 
    { 
    return (T)(object)"nothing"; 
    } 

    return default(T); 
} 
+0

Sí, esa era la misma solución que la anterior. Supongo que solo tuve que lanzar a un objeto primero, ya que no hay conversión directa de int a T. Pero hay un elenco de int a objeto y objetar a T. ¿Es correcto? – Deane

+0

Porque comprueba si typeof (T) sí. Realmente, la cláusula else debería verificar el tipo de letra (cadena), de lo contrario algo como MyMethod fallaría. Editaré el ejemplo. – dkackman

0

Esto no es t válido ya que no hay garantía de que T sea moldeable/convertible en cadena o int.

Los genéricos NO son variantes, es decir, tipos que pueden contener nada, se resuelven en tiempo de compilación a un tipo real. Tu código no se compila porque no debería. Puede solucionar los problemas de tiempo de compilación utilizando algunos de los hacks publicados aquí, pero este es realmente un problema de lógica. Da un paso atrás y vuelve a pensar en lo que estás tratando de hacer en lugar de tratar de evitar el compilador.

+0

¿Puedo restringir de alguna manera que T sea solo string o int? – Deane

+0

@Deane - no puede – dkackman

+0

@Deane - En VB o en lenguajes con scripts similares, puede devolver lo que quiera de una función: int, cadena, float, página, referencia del servicio web, qué tiene usted. En los lenguajes fuertemente tipados, ese no es el caso, porque el compilador espera que usted tome el control de los reinados y no deje que haga su trabajo por usted. ¿Qué aspecto tiene el CÓDIGO DE LLAMADAS que necesita este tipo de resultado? –

1

poco fuera de tema, pero si usted está tratando de hacer esto, entonces puede ser que su diseño está mal ...

Por qué no sobrecargar el método y establecer el resultado como un parametro a cabo:

void MyMethod(out int result) 
{ 
    result=0; 
} 

void MyMethod(out string result) 
{ 
    result="my value"; 
} 

entonces se puede decir:

int value; 
MyMethod(out value); 

Y el compilador seleccionar la versión correcta

+0

¿No es un uso correcto de los genéricos el poder usar la misma lógica para diferentes tipos? Solo tengo un método que tiene un montón de lógica, pero en diferentes situaciones, necesito diferentes tipos de ella. ¿No es esta la forma correcta de usar genéricos? – Deane

+0

Pero está activando el tipo, lo que causará un problema ... Publicaré una alternativa – Sean

+0

Sí, eso funcionaría. Simplemente, menos elegante parece, porque ahora tengo tres métodos: uno para cada tipo y otro para la lógica central. ¿Por qué el encendido es un problema? – Deane

Cuestiones relacionadas