2012-09-25 11 views
24

Me gusta enviar una función de convertidor de tipo genérico a un método, pero no puedo encontrar la manera de hacerlo.¿Cómo puedo pasar un func con un parámetro de tipo genérico?

Aquí hay una sintaxis no válida que explica lo que me gusta de lograr, el problema es que no sé cómo especificar el tipo genérico junto con mi func:

public void SomeUtility(Func<T><object,T> converter) 
{ 
    var myType = converter<MyType>("foo"); 
} 

Editar (véase también mi discusión en los comentarios con Lawrence): Por "convertidor de tipo genérico" que quería decir me gustaría pasar en un convertidor que puede convertir a cualquier tipo fuerte <T> (no objeto), por lo que la siguiente línea en mi método podría ser:

var myOtherType = converter<MyOtherType>("foo"); 

El delegado me gusta p culo como un parámetro sería algo como esto:

private delegate TOutput myConverterDelegate<TOutput>(object objectToConvert); 

Esto es más un # exploración sintaxis/C ahora, para hacer las cosas, probablemente voy a utilizar una interfaz vez, pero espero que esto es posible de lograr con una func/delegate.

+0

¿Es significativo el hecho de que haya especificado un tipo dentro del cuerpo del método? ¿Está insinuando que este método puede necesitar realizar conversiones contra varios tipos, en lugar de un tipo específico definido por la persona que llama? –

+0

Sí, eso fue lo que traté de expresar como un "convertidor de tipo genérico", por lo que la siguiente línea podría ser var myOtherType = converter ("foo"); – joeriks

+0

Ok, entonces creo que encontrarás mi respuesta útil :) –

Respuesta

19

No se puede tener instancias de funciones o acciones genéricas - todos los parámetros de tipo se definen por adelantado y no puede ser redefinido por la persona que llama.

Una manera fácil sería evitar por completo el polimorfismo apoyándose en los pies en la fundición:

public void SomeUtility(Func<Type, object, object> converter) 
{ 
    var myType = (MyType)converter(typeof(MyType), "foo"); 
} 

Si desea escribir la seguridad, es necesario aplazar la definición de los parámetros de tipo a la persona que llama. Usted puede hacer esto mediante la composición de un método genérico dentro de una interfaz:

public void SomeUtility(IConverter converter) 
{ 
    var myType = converter.Convert<MyType>("foo"); 
} 

interface IConverter 
{ 
    T Convert<T>(object obj); 
} 

Editar:

Si el 'tipo de convertidor' se conoce en la llamada in situ, y sólo este tipo se utilizará en el interior el método de utilidad, luego puede definir un tipo genérico en el método y usarlo, tal como lo sugirieron otros carteles.

+0

Ok gracias, sí, probablemente solo use una interfaz, gracias por indicarme esa dirección. Pero, por interés, ¿no debería un delegado/un func transmitir un tipo genérico? Descrito como un delegado, supongo que lo escribiría como: delegado privado TOutput myConverterDelegate (object objectToConvert); - pero cuando trato de usar eso como un parámetro me sale "requiere 1 tipo de argumentos" – joeriks

+1

Definitivamente puedes * definir * delegados genéricos, después de todo, eso es exactamente lo que Func y Action son. Se tratan como * definiciones genéricas *, al igual que las interfaces genéricas y las clases. Sin embargo, no puede usar * definiciones genéricas * en las firmas de métodos, solo * tipos genéricos * parametrizados. Simplemente no puedes hacer lo que estás tratando de lograr con un delegado solo. –

7

Necesita hacer SomeUtility genérico también. Hacer esto y la fijación de la sintaxis da:

public void SomeUtility<T>(Func<object,T> converter) 
{ 
    var myType = converter("foo"); 
} 
15
public void SomeUtility<T>(Func<object, T> converter) 
{ 
    var myType = converter("foo"); 
} 

y luego:

SomeUtility(arg => new MyType()); 

La inferencia de tipos genéricos funcionará en este caso.

+0

este debería ser aceptado –

3

Debe conocer el tipo de T en tiempo de compilación para usarlo. La T se puede especificar a nivel de clase o a nivel de método.

class SomeClass<T> { 
    public void SomeUtility(Func<object, T> converter) { 
     var myType = converter("foo"); // Already is the T-type that you specified. 
    } 
} 

o

public void SomeUtility<T>(Func<object, T> converter) { 
    var myType = converter("foo"); // Already is the T-type that you specified. 
} 
Cuestiones relacionadas