2012-05-02 13 views
9

Spero che qualcuno qui possa spiegare quali supposizioni errate sto facendo. In C# 4.0, ho 2 interfacce e una classe che li implementa entrambi. In un metodo dichiaro una variabile con il tipo della prima interfaccia, un'istanza utilizzando la classe che implementa entrambe le interfacce e può in qualche modo lanciare con successo per la seconda interfaccia come nel codice seguente:Trasmissione di un'interfaccia a un'altra interfaccia che non eredita

public interface IFirstInterface 
    { 
     void Method1(); 
    } 

    public interface ISecondInterface 
    { 
     void Method2(); 
    } 

    public class InterfaceImplementation : IFirstInterface, ISecondInterface 
    { 
     public void Method1() { } 
     public void Method2() { } 
    } 

    public class SomeClass 
    { 
     public void SomeMethod() 
     { 
      IFirstInterface first = new InterfaceImplementation(); 
      first.Method1(); 

      // Shouldn't the next line return null? 
      ISecondInterface second = first as ISecondInterface; 
      // second is not null and the call to Method2() works fine 
      second.Method2(); 
     } 
    } 

Sono cercando di capire perché il casting ha avuto successo. Sì, la classe implementa entrambe le interfacce, ma penserei che dal momento che la prima variabile sia dichiarata come IFirstInterface (che non eredita da ISecondInterface), il cast dovrebbe ancora fallire.

Ho anche provato a ristrutturare il mio codice in altri modi, come non usare 'come', ma il cast ha ancora successo.

Cosa mi manca?

risposta

7

Dall'esempio, si consiglia di verificare il tipo di tipo prima di chiamare qualsiasi funzionalità. La prima creazione creerà una "InterfaceImplementation" pienamente qualificata che supporta entrambe le interfacce. Tuttavia, lo stai inserendo in un tipo dichiarato di solo la prima interfaccia. Quindi, dal punto di vista del "primo" oggetto, si preoccupa solo di qualsiasi cosa associata come implementazione IFirstInterface.

Ora, al secondo ... Anche se hai creato l'oggetto, puoi ancora chiedere ... A proposito ... sei anche una seconda interfaccia? Se sì, fai questo ...

IFirstInterface first = new InterfaceImplementation(); 

if(first is ISecondInterface) 
    // typecast since the second interface is legit, then call it's method 2 
    ((ISecondInterface)first).Method2(); 
+0

Ciò conferma quello che pensavo stesse succedendo. Grazie –

+0

Molte molte grazie, davvero necessarie. +1 (+10 se potessi). – Arjang

0

Se si guarda dal punto di vista dell'oggetto concreto, si può dire "I'm a IFirstInterface, ma sono anche un ISecondInterface". È questo che vuoi dire? La domanda che hai descritto, finirà per fondere solo all'interno di una catena di successione/implementazione.

1

L'unica cosa che ti manca è che è esattamente come deve essere, e questa è una funzione utile, non un problema. Quando si esegue il casting, si può pensare al codice come fondamentalmente dicendo: "Non mi interessa sapere che tipo di oggetto era, voglio vedere se può essere convertito in tipo T". In questo caso, poiché l'oggetto sottostante è di tipo InterfaceImplementation, indipendentemente dal fatto che sia attualmente noto come IFirstInterface, la risposta è che sì, può essere convertito in ISecondInterface.

0

Benvenuti al polimorfismo. L'oggetto first sarà sempre un'istanza di InterfaceImplementation. Il modo in cui scegli di fare riferimento a esso non influisce su ciò che l'oggetto è veramente "." Questo è il modo in cui il concetto di astrazione funziona nel suo complesso.

3

Il tipo effettivo dell'istanza first punta all'implementazione di entrambe le interfacce. Quindi ovviamente sia Method1 sia Method2 sono disponibili sull'oggetto.

Il tipo statico di first consente solo di accedere a Method1. Il tipo statico di second consente solo di accedere a Method2. Se si dichiara un riferimento all'oggetto utilizzando una delle interfacce, è sufficiente selezionare per visualizzare l'istanza come oggetto che soddisfa il contratto selezionato (l'interfaccia).

Poiché InterfaceImplementation implementa entrambe le interfacce, è possibile fare riferimento all'istanza utilizzando una delle due interfacce.

Problemi correlati