2010-02-05 12 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; 
    } 
} 

C'è qualche differenza (CallHidden1 vs. CallHidden2) è un codice compilato? Esistono altre differenze tra dove T: Foo e dove T: Foo, IBar (se Foo implementa IBar) che accede ai membri dell'interfaccia esplicitamente implementati?Interfaccia esplicitamente implementata e vincolo generico

risposta

1

Sì, un pochino, poiché il secondo specifica che l'interfaccia deve essere implementata, che può diventare importante se lo Foo viene successivamente modificato in modo che non implementi IBar.

che renderebbe inadatto per essere utilizzato in CallHidden2<> rimanendo valida in fase di compilazione per CallHidden1<> (che poi sicuro durante l'esecuzione se IBar non viene più attuato da Foo).

Quindi, se si trovano in gruppi separati, i diversi metadati farebbero la differenza. L'IL eseguito, tuttavia, sarà abbastanza simile se non uguale.

6

L'IL generato è leggermente diverso:

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() 

Se T erano un tipo di valore, ne risulterebbe foo essere inscatolato in CallHidden1 ma non in CallHidden2. Tuttavia, dal momento che Foo è una classe, qualsiasi tipo Foo derivante da Foo non sarà un tipo di valore e pertanto il comportamento sarà identico.

Problemi correlati