2012-04-14 11 views
17

En mi intento de comprender C# correctamente, me pregunto cuáles son las diferencias prácticas entre especificar una restricción de interfaz en un argumento de método genérico y simplemente especificar la interfaz como el tipo de argumento.Restricción de interfaz en argumentos de método genérico

public interface IFoo 
{ 
    void Bar(); 
} 

public static class Class1 
{ 
    public static void Test1<T> (T arg1) where T : IFoo 
    { 
     arg1.Bar(); 
    } 

    public static void Test2(IFoo arg1) 
    { 
     arg1.Bar(); 
    } 
} 

EDITAR

sé mi ejemplo es muy estrecha, ya que es sólo un ejemplo. Estoy bastante interesado en las diferencias que están fuera de su alcance.

+0

Posible duplicado de [ventaja práctica de los genéricos frente a las interfaces] (http://stackoverflow.com/questions/7224675/practical-advantage -of-generics-vs-interfaces) –

Respuesta

12

En su ejemplo específico, no hay diferencia. Pero tomar el siguiente método:

public static class Class1 
{ 
    public static T Test1<T>(T arg1) where T : IFoo 
    { 
     arg1.Bar(); 
     return arg1; 
    } 

    public static IFoo Test2(IFoo arg1) 
    { 
     arg1.Bar(); 
     return arg1; 
    } 
} 

Test1 devolverá el tipo específico de arg1, mientras que Test2 sólo devolverá la interfaz. Esto se usa a menudo en interfaces fluidas.


ejemplo extendido:

public interface IFoo 
{ 
    void Bar(); 
} 

public class Foo : IFoo 
{ 
    // implementation of interface method 
    public void Bar() 
    { 
    } 

    // not contained in interface 
    public void FooBar() 
    { 
    } 
} 


var foo = new Foo(); 
Class1.Test1(foo).FooBar(); // <- valid 
Class1.Test2(foo).FooBar(); // <- invalid 
6

No hay una pizca de diferencia por el ejemplo que has dado. Por otro lado, el uso de la versión genérica le brinda la posibilidad de ampliar la lista de restricciones (where T : IFoo, IOther) en el futuro, sin cambiar la firma del método.

+0

+1 para la extensión de restricción – Ucodia

0

Es todo una cuestión de tipo de fundición. Si su método debe devolver T, entonces Test1 no requerirá conversión y, como Test2 solo devuelve una interfaz, necesitará conversión de tipos explícita o implícita para obtener el tipo final.

0

A menudo, la restricción de interfaz se combina con, p. IFoo, new()

... que le permite manipular objetos como T por completo, crear, inicializar colecciones, etc. - y devolver T como se sugiere. Mientras que con la interfaz solo no sabes qué clase (T) es en realidad.

4

Me gustaría poner un poco de énfasis en las respuestas que otros han dado.

HAY UNA diferencia entre Test(IFoo foo) y Test<T>(T foo) where T : IFoo. Hay una diferencia real al igual que hay una gran diferencia entre List<object> (o, digamos ArrayList, que recibe un object) y List<string>.

Test (IFoo foo), le da los beneficios de polimorfismo y tipo de herencia, al igual que List<object>. Le permite construir una clase que maneje todos los tipos IFoo. Pero a veces no solo quiero el polimorfismo, quiero una lista que solo contenga cadenas, y List<string> me da eso sin requerir que escriba un contenedor fuertemente tipado sobre ArrayList.

Lo mismo para su código. Digamos que tengo un class Comparer<T> where T:IFoo. Quiero poder utilizar esta clase para comparar objetos Foo1 entre sí, o para comparar Foo2 entre sí, pero no quiero poder comparar Foo1 con Foo2.Un método genérico inflexible que hará cumplir, mientras que uno polimórfica no lo haría:

public class Comparer 
{ 
    public bool Compare1<T>(T first, T second) where T : IFoo {...} 
    public bool Compare2 (IFoo first, IFoo second) {...} 
} 

Foo1 first = new Foo1(); 
Foo2 second = new Foo2(); 
myComparer.Compare1(first, second); // won't compile! 
myComparer.Compare2(first, second); // Compiles and runs. 
+2

Esto aún compilará: 'myComparer.Compare1 (primero, segundo);' –

+1

Sí, pero está haciendo que sea EXPLÍCITO que acepte cualquier objeto 'IFoo', que está bien. Al igual que puedo llamar a 'myComparer.Compare1 (" whatever ", 5)'. –

+2

Eso no compilaría porque 'object' no es un' IFoo'. –

Cuestiones relacionadas