2010-03-22 14 views
6

En esta sección de una función (.NET 2.0):.Conversiones entre tipos de valor en una clase utilizando genéricos

public void AttachInput<T>(T input) where T : struct 
{ 
    if (input is int) 
    { 
     Inputs.Add((int)input); 
    } 
} 

El compilador muestra el error "No se puede convertir tipo 'T' a 'int'
? Por lo tanto, he usado Convert.ToInt32() que funcionaba - pero él caja input a un objeto ¿hay una mejor solución Gracias

Edit1: despegado cosas innecesarias en relación con la cuestión

Edit2: Tomando una mirada más profunda? en genéricos, me parece que Convert.ToInt32 cuando T ya es un int no encajona en un objeto y su sobrecarga int es la llamada.

Si eso es cierto, los métodos Convert me parecen ser la mejor opción en el momento

+1

Me resulta difícil imaginar dónde utilizarías esto, ¿puedes dar un poco más de contexto? Es posible que un método genérico no sea el mejor enfoque aquí. –

+0

Estoy haciendo un árbol de clases de operador, que pueden mostrar valores de acuerdo con sus entradas. La cosa es que estas clases pueden aceptar valores o tipos de referencia, y tengo otra función que es "public void AttachInput (entrada de objeto)", que tenía la intención de usar solo para tipos de referencia. Mi intención era discernir entre tipos de referencia y tipos de valores, evitando el boxeo –

+0

He actualizado mi respuesta con más información sobre su teoría sobre Convert.ToInt32 y el boxeo. –

Respuesta

5

Para la seguridad de tipos y la evitación de boxeo, su única opción es una sobrecarga específica para la entrada del tipo int:

public void AttachInput(int input) 
{ 
    Inputs.Add(input); 
} 

actualización:

el PO ha actualizado a la pregunta con una teoría:

Tomando una mirada más profunda en los genéricos, que me parece que cuando Convert.ToInt32 T ya es un entero no hay boxeo para un objeto y su sobrecarga int es el uno que se llama.

Esto no está bien, y una simple prueba puede demostrarlo. Supongamos que escribimos nuestro propio conjunto de sobrecargas sólo para detectar cuál esté siendo llamados:

public static class OverloadTest 
{ 
    public static void Foo(int x) 
    { 
     Console.WriteLine("Foo(int)"); 
    } 

    public static void Foo(bool x) 
    { 
     Console.WriteLine("Foo(bool)"); 
    } 

    public static void Foo(object x) 
    { 
     Console.WriteLine("Foo(object)"); 
    } 
} 

Ahora escribimos un método genérico para modelar la una de la pregunta: ¿

static void CallTheRightFoo<T>(T value) where T : struct 
{ 
    OverloadTest.Foo(value); 
} 

La teoría es que debido el CLR/JIT producirá una versión específica del método para cada tipo de valor, puede seleccionar la sobrecarga específica para int ya que hay una disponible.

Así que aquí está la prueba:

struct Test { } // in order to test a user-defined value type 

static void Main(string[] args) 
{ 
    CallTheRightFoo(1); 
    CallTheRightFoo(true); 
    CallTheRightFoo(new Test()); 
} 

La salida es:

Foo(object) 
Foo(object) 
Foo(object) 

relacionar esto con Convert.ToInt32, a partir del código genérico que siempre será llamando a la sobrecarga que acepta object, y por lo el valor habrá sido encuadrado y luego deberá ser desempaquetado dentro de Convert.ToInt32 (que también debe verificar qué tipo es primero).

A pesar de reiterar un punto importante detrás de todo esto: si bien el boxeo/unboxing es más caro en comparación con no hacerlo, que es, posiblemente, de un costo insignificante en comparación con cualquier trabajo real de su código está haciendo.Así que no me preocuparía demasiado por el costo hasta que pueda demostrar que es una carga real para un modelo realista de una aplicación que usa su biblioteca.

+0

Bueno, supongo que tendré que hacer eso entonces, gracias. Lamentablemente, me parece que el único uso para las restricciones struct es usarlo combinado con la palabra clave predeterminada, pero esa es solo una pregunta diferente –

+0

Básicamente 'struct' no es tan útil en muchos sentidos, ya sea como una restricción o para definir nuestra tipos propios Tiene una ventaja de rendimiento teórico, pero el GC es tan bueno que pocas aplicaciones realmente notan alguna diferencia. –

+0

Guau, tienes toda la razón. Sin embargo, es triste que la única forma de evitar el boxeo es crear sobrecargas. Muchas gracias –

Cuestiones relacionadas