2009-05-04 9 views
2
interface I { int J(); } 

class A : I 
{ 
    public int J(){return 0; } // note NOT virtual (and I can't change this) 
} 

class B : A, I 
{ 
    new public int J(){return 1; } 
} 


B b = new B(); 
A a = b; 
I ib = b, ia = a; 

b.J(); // should give 1 
a.J(); // should give 0 (IMHO) 

ia.J(); // ??? 
ib.J(); // ??? 

Je sais que je pouvais essayer, mais je suis à la recherche d'une bonne source de autorité pour ce coin tout et je préfère ne pas simplement commencer à creuser myopes à travers les textes MSDN (Je n'ai aucune idée de ce que Google pour).Comment cela fonctionnera-t-il? (interfaces et fonctions non virtuelles)

+0

La mise en œuvre de l'interface * et * à l'aide du qualificatif «nouveau» est à la fois redondante et confuse. La 'nouvelle' implémentation est destinée à permettre à une sous-classe d'avoir une implémentation qui diffère de sa classe de base pour les cas où elle est appelée explicitement. Si la classe de base implémente explicitement l'interface, alors * je pense * vous pourriez obtenir (IFace) Child.IMethod() = A; (Base) Child.IMethod() = B; (Enfant) Child.IMethod = C – STW

+0

Vous êtes dans l'erreur (voir mon commentaire sur votre message) mais en bref sans le "je" sur B, IJ est mis en œuvre par AJ même sur B (je l'ai testé) – BCS

+0

Vous ' re right, mon exemple était si B: A, pas B: A, je ... Plutôt que d'avoir B: A, je pourrais vous faire B: I et utiliser une instance interne de A pour fournir cette fonctionnalité et exposer ses méthodes publiquement ? – STW

Répondre

1

Peu importe que vous parlez au contrat fourni par une classe de base ou de l'interface, ils seront tous de retour 1 parce que vous parlez à une instance de la classe B.

+0

avez-vous un lien vers une référence officielle? Je cherche plus "le reste de l'histoire" que cette question exacte. – BCS

+0

C# est un langage d'expédition unique qui signifie que la méthode à appeler est déterminée par le type de l'objet dans tous les cas le type est B. –

2

Réécriture: Puisque nous sommes parler de l'implémentation d'IDisposable ce que vraiment fait c'est s'assurer que les classes Derived et Base ont l'opportunité d'exécuter leur code de nettoyage respectif. Cet exemple couvrira 2/3 du scénario; Cependant, comme il dérive de Base() et de Base.Dispose() n'est pas virtuel, les appels faits à ((Base) Child) .Dispose() ne fourniront pas à la classe Child la possibilité de nettoyer.

La seule solution consiste à ne pas dériver Child from Base; Cependant, cela a été exclu. Appels à ((IDisposable) enfant) .Dispose() et Child.Dispose() permettront à Child et Base d'exécuter leur code de nettoyage.

class Base : IDisposable 
{ 
    public void Dispose() 
    { 
     // Base Dispose() logic 
    } 
} 

class Child : Base, IDisposable 
{ 
    // public here ensures that Child.Dispose() doesn't resolve to the public Base.Dispose() 
    public new void Dispose() 
    { 
     try 
     { 
      // Child Dispose() logic 
     } 

     finally 
     { 
      // ensure that the Base.Dispose() is called 
      base.Dispose(); 
     } 
    } 

    void IDisposable.Dispose() 
    { 
     // Redirect IDisposable.Dispose() to Child.Dispose() 
     Dispose(); 
    } 
} 
+0

Je ne peux pas modifier la classe de base (c'est une classe de .NET) et la méthode en question n'est pas virtuel, donc je ne peux pas faire vos meilleures pratiques dans ce cas. Toujours dans le cas non virtuel, passer de "B: A, I" à "B: A" modifie les choses (je les ai testées et pour obtenir le nouveau J à utiliser, le "I" explicite est nécessaire.) – BCS

+0

Un exemple réel peut être plus utile qu'un problème d'histoire mathématique :) – STW

+0

J'essaie d'ajouter des choses aux actions IDisposable pour FileSystemWatcher. – BCS

1

Jeffrey Richter (CLR via C#): « Le compilateur C# exige qu'une méthode qui implémente Si vous n'êtes pas explicitement une interface marquée comme publique Le CLR exige que les méthodes d'interface marquées comme virtuelle.. marque la méthode comme virtuelle dans votre code source, le compilateur marque la méthode comme virtuelle et scellé, ce qui empêche une classe dérivée de surcharger la méthode d'interface Si vous explicitement marque la méthode comme virtuelle, le compilateur marque la méthode comme virtuelle (et le laisse non scellé); cela permet à une classe dérivée de remplacer la méthode d'interface "

Questions connexes