Perché una classe C # può ereditare da un'unica interfaccia sia implicitamente che esplicitamente?

StackOverflow https://stackoverflow.com/questions/253058

Domanda

Oggi trovo che una classe C # possa ereditare un'interfaccia sia in modo implicito che esplicito. Questo mi sorprende. Se C # funziona in questo modo, un'istanza può comportarsi diversamente quando viene referenziata in modo diverso.

interface IFoo
{
    void DoSomething();
}

class Foo : IFoo
{
    #region IFoo Members
    public void DoSomething()
    {
        Console.WriteLine("do something implicitly");
    }
    #endregion

    #region IFoo Members
    void IFoo.DoSomething()
    {
        Console.WriteLine("do something explicitly");
    }
    #endregion
}


        Foo f = new Foo();
        f.DoSomething();

        ((IFoo)f).DoSomething();

Il codice sopra viene eseguito e generato

do something implicitly
do something explicitly

Credo che questo progetto di C # faccia incoerenza di comportamento. Forse è obbligatorio che una classe C # possa ereditare da un'interfaccia in modo implicito o esplicito, ma non entrambi.

C'è qualche motivo per cui C # è progettato in questo modo?

È stato utile?

Soluzione

Il tuo esempio non implementa IFoo sia implicitamente che esplicitamente. Implementate solo IFoo.DoSometing () in modo esplicito. Hai un nuovo metodo nella tua classe chiamato DoSomething (). Non ha nulla a che fare con IFoo.DoSomething, tranne per il fatto che ha lo stesso nome e parametri.

Altri suggerimenti

Ogni classe che implementa un'interfaccia ha una mappatura tra i membri di quella classe e i membri dell'interfaccia. Se la classe esplicitamente implementa un membro dell'interfaccia, l'implementazione esplicita sempre verrà mappata all'interfaccia. Se non esiste un'implementazione esplicita, è prevista un'implementazione implicita, che verrà mappata sull'interfaccia.

Quando una classe ha lo stesso nome di membro e tipi associati di un'interfaccia ma implementa esplicitamente anche il membro corrispondente per l'interfaccia, quindi il " implicito " l'implementazione non è considerata un'implementazione dell'interfaccia affatto (a meno che l'implementazione esplicita non la chiami).

Oltre ai diversi significati in ogni caso in cui la classe implementa più interfacce con lo stesso nome / tipo di membro, anche con una sola interfaccia, la classe stessa è considerata avere un'interfaccia implicita che potrebbe hanno gli stessi membri / tipi della sola interfaccia ma significano comunque qualcosa di diverso.

Questo lo rende più flessibile in caso di collisioni. In particolare, guarda IEnumerator e IEnumerator<T> - entrambi hanno una proprietà Current, ma di tipi diversi . devi utilizzare l'implementazione esplicita dell'interfaccia per implementare entrambi (e il modulo generico estende il modulo non generico).

Eredità multipla: E se derivassi da due interfacce che definiscono lo stesso metodo per scopi diversi?

  interface IMoveable
  {
    public void Act();
  }

  interface IRollable
  {
    public void Act();
  }

  class Thing : IMoveable, IRollable
  {
    //TODO Roll/Move code here

    void IRollable.Act()
    {
      Roll();
    }

    void IMoveable.Act()
    {
      Move();
    }
  }

Ragazzi, grazie per le risposte.

Si scopre che " La classe C # può ereditare un'interfaccia in modo implicito ed esplicito allo stesso tempo " è in realtà un'illusione. In realtà, una classe può ereditare un'interfaccia per una volta.

Nella domanda originale, il " DoSomething " il metodo sembra " implementa implicitamente " interfaccia IFoo (il metodo è effettivamente generato da VS2008), ma in realtà NON lo è. Con l'implementazione esplicita dell'interfaccia IFoo, il & Quot; DoSomething & Quot; il metodo diventa solo un metodo normale che non ha nulla a che fare con IFoo se non con la stessa firma.

Credo ancora che sia un progetto complicato di C #, ed è facile usarlo erroneamente. Dì, ho del codice come questo

        Foo f = new Foo();
        f.DoSomething();

Ora, voglio rifattarlo al di sotto del codice. Sembra perfettamente OK, ma il risultato dell'esecuzione è diverso.

        Action<IFoo> func = foo => foo.DoSomething();
        func(f);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top