2010-02-05 9 views
7
interface IBar { void Hidden(); } 

class Foo : IBar { public void Visible() { /*...*/ } void IBar.Hidden() { /*...*/ } } 

class Program 
{ 
    static T CallHidden1<T>(T foo) where T : Foo 
    { 
     foo.Visible(); 
     ((IBar)foo).Hidden(); //Cast required 

     return foo; 
    } 

    static T CallHidden2<T>(T foo) where T : Foo, IBar 
    { 
     foo.Visible(); 
     foo.Hidden(); //OK 

     return foo; 
    } 
} 

¿Hay alguna diferencia (CallHidden1 vs. CallHidden2) es el código compilado real? ¿Existen otras diferencias entre dónde T: Foo y dónde T: Foo, IBar (si Foo implementa IBar) que en el acceso a los miembros de la interfaz implementados explícitamente?Interfaz explícitamente implementada y restricción genérica

Respuesta

1

Sí, un poquito, ya que el segundo especifica que la interfaz debe implementarse, lo que puede volverse importante si Foo se modifica posteriormente para que no implemente IBar.

que lo hagan inadecuado para ser utilizado en CallHidden2<> sin dejar de ser válida en tiempo de compilación para CallHidden1<> (que luego fallar en tiempo de ejecución si IBar ya no está siendo implementado por Foo).

Por lo tanto, si están en ensamblajes separados, los diferentes metadatos marcarían la diferencia. El IL ejecutado, sin embargo, será bastante similar si no es el mismo.

6

La IL generado es ligeramente diferente:

L_000d: ldarg.0 
    L_000e: box !!T 
    L_0013: callvirt instance void WindowsFormsApplication1.IBar::Hidden() 

vs.

L_000d: ldarga.s foo 
    L_000f: constrained !!T 
    L_0015: callvirt instance void WindowsFormsApplication1.IBar::Hidden() 

Si T eran un tipo de valor, esto resultaría en foo siendo encajonado en CallHidden1 pero no en CallHidden2. Sin embargo, dado que Foo es una clase, cualquier tipo T derivado de Foo no será un tipo de valor y, por lo tanto, el comportamiento será idéntico.

Cuestiones relacionadas