3

Je ne suis pas sûr de ce qui se passe. J'ai la classe de base suivante:Propriété C# non disponible dans la classe dérivée

public class MyRow : IStringIndexable, System.Collections.IEnumerable, 
    ICollection<KeyValuePair<string, string>>, 
    IEnumerable<KeyValuePair<string, string>>, 
    IDictionary<string, string> 
{ 
    ICollection<string> IDictionary<string, string>.Keys { } 
} 

Et puis j'ai cette classe dérivée:

public class MySubRow : MyRow, IXmlSerializable, ICloneable, 
    IComparable, IEquatable<MySubRow> 
{ 
    public bool Equals(MySubRow other) 
    { 
     // "MyRow does not contain a definition for 'Keys'" 
     foreach (string key in base.Keys) { } 
    } 
} 

Pourquoi dois-je obtenir cette erreur? "'MyNamespace.MyRow' ne contient pas de définition pour 'Keys'". Les deux classes sont dans l'espace de noms MyNamespace. J'ai essayé d'accéder à this.Keys et base.Keys et aucun ne fonctionne depuis MySubRow. J'ai essayé de marquer la propriété Keys comme public dans MyRow mais j'ai obtenu "Le modificateur 'public' n'est pas valide pour cet article", je pense qu'il est nécessaire d'implémenter une interface.

Répondre

7

Vous implémentez explicitement la propriété Keys. Si vous souhaitez rendre ce membre accessible au public (ou protected), remplacez IDictionary<string, string>.Keys par Keys et ajoutez le modificateur de visibilité approprié devant lui.

public ICollection<string> Keys { ... } 

ou

protected ICollection<string> Keys { ... } 

Vous pouvez faire référence à base comme une instance de IDictionary<string, string> ainsi:

((IDictionary<string, string>)base).Keys 

Plus d'informations

(à en juger par vos commentaires que vous semblent être fami ment avec la distinction, mais d'autres peuvent ne pas l'être)

La mise en œuvre de l'interface C# peut se faire de deux façons: implicitement ou explicitement. Considérons cette interface:

public interface IMyInterface 
{ 
    void Foo(); 
} 

Une interface est juste un contrat pour ce que les membres d'une classe doivent mettre à la disposition du code qui l'appelle. Dans ce cas, nous avons une fonction appelée Foo qui ne prend aucun paramètre et ne renvoie rien. Une implémentation d'interface implicite signifie que vous devez exposer un membre public qui correspond au nom et la signature du membre de l'interface, comme ceci:

public class MyClass : IMyInterface 
{ 
    public void Foo() { } 
} 

Cela satisfait l'interface, car il expose un membre public sur la classe qui correspond à chaque membre sur l'interface. C'est ce qui est habituellement fait. Cependant, il est possible de explicitement implémenter l'interface et cartographier la fonction d'interface à un private membre:

public class MyClass : IMyInterface 
{ 
    void IMyInterface.Foo() { } 
} 

Cela crée une fonction privée sur MyClass qui est accessible uniquement aux personnes de l'extérieur quand ils font référence à une instance de IMyInterface. Par exemple:

void Bar() 
{ 
    MyClass class1 = new MyClass(); 
    IMyInterface class2 = new MyClass(); 

    class1.Foo(); // works only in the first implementation style 
    class2.Foo(); // works for both 
} 

implémentations explicites sont toujours privé. Si vous voulez l'exposer en dehors de la classe, vous devrez créer un autre membre et l'exposer, puis utiliser l'implémentation explicite pour appeler l'autre membre.Ceci est généralement fait pour qu'une classe puisse implémenter des interfaces sans encombrer son API publique, ou si deux interfaces exposent des membres avec le même nom.

+0

L'OP accède au membre, ne cherche pas à mettre en œuvre il – JaredPar

+0

@Jared: Regardez son premier cours. La propriété est implémentée là, et c'est fait explicitement. –

+0

@Adam, gotcha, manqué l'implémentation explicite – JaredPar

3

Puisque vous implémentez IDictionary < TKey, l'interface TValue > explicitement, vous devez d'abord jeter this à IDictionary<string,string>:

public bool Equals(MySubRow other) 
{ 
    foreach (string key in ((IDictionary<string,string>)this).Keys) { } 
} 
+0

Merci. J'ai fini par supprimer la déclaration d'interface explicite dans 'MyRow'. Maintenant, c'est juste 'public ICollection Keys' et l'appel' base.Keys' fonctionne. –

+0

@Sarah, dans certaines situations, vous devrez utiliser ce que @dtb a suggéré, car plusieurs interfaces définiront le même nom de méthode ... –

+0

@Rob: c'est en fait ce que j'avais fait dans le passé et puis, à la suite de refactoring, réduit les interfaces implémentées par la classe, de sorte que l'implémentation explicite n'était plus nécessaire. –

0

Je crois à la fois Jared et Adam sont corrects: la propriété est mis en œuvre sur explitcity la classe de base, ce qui fait qu'elle n'est pas publique. Vous devriez être en mesure de le changer à une mise en œuvre implicite et de le rendre heureux:

public class MyRow : IStringIndexable, System.Collections.IEnumerable, 
    ICollection<KeyValuePair<string, string>>, 
    IEnumerable<KeyValuePair<string, string>>, 
    IDictionary<string, string> 
{ 
    ICollection<string> Keys { } 
} 
+0

Je l'ai fait implicite et 'public', oui. –

0

protected permettra héritant des classes de le voir, mais aucune autre classe

+0

Ce n'était pas le problème, cependant. Je ne pouvais pas le marquer comme 'public' ou' protected' car j'utilisais explicitement l'interface. En l'implémentant explicitement, l'ajout d'un modificateur comme 'public' a provoqué une erreur de compilation séparée. J'ai fini par en faire une implémentation implicite, _then_ ajoutant 'public':' public ICollection Keys'. –