2010-07-29 4 views
4

Si j'écris classe, puis tous oksans se cacher

class C 
{ 
    protected int _attr; 
    int attr { get { return _attr; } } 
} 

class CWithSet : C 
{ 
    int attr { set { _attr = value; } } 
} 

Mais, si j'écris l'interface

interface I 
{ 
    int attr { get; } 
} 

interface IWithSet : I 
{ 
    int attr { set; } 
} 

alors je désunis « membre 'IWithSet.attr' cache hérité ' I.attr 'Utilisez le nouveau mot-clé si la dissimulation était voulue. " Comment écrire, afin de ne pas recevoir d'avertissement?

Répondre

3

Vous voudrez peut-être examiner si cela vaut la peine de redéfinir la sémantique de vos interfaces. Ce que je veux dire, c'est qu'il peut être logique d'avoir une interface séparée en écriture seule en plus de celle en lecture seule que vous avez définie comme "je".

Voici un exemple:

interface IReadOnly 
{ 
    int Attr { get; } 
} 

interface IWriteOnly 
{ 
    int Attr { set; } 
} 

interface I : IReadOnly, IWriteOnly 
{ 
} 

class CReadOnly : IReadOnly 
{ 
    protected int _Attr; 
    public int Attr 
    { 
     get { return _Attr; } 
    } 
} 

class C : CReadOnly, I 
{ 
    public int Attr 
    { 
     get { return base.Attr; } 
     set { _Attr = value; } 
    } 
} 

EDIT: J'ai changé la partie get de la propriété C.Attr être return base.Attr au lieu de return _Attr; afin d'être plus conforme à l'exemple de code dans la question initiale. Je pense aussi que c'est plus correct, car vous pouvez avoir une logique plus compliquée définie dans CReadOnly.Attr que vous ne voulez pas dupliquer.

Certaines des interfaces et des classes ont été renommées à partir de l'exemple d'origine. "Je" devint "IReadOnly", et "IWithSet" devint "I". "C" est devenu "CReadOnly", et "CWithSet" est devenu "C".

Ceci a compilé pour moi sans avertissements.

EDIT: Cela a été compilé pour moi sans aucun avertissement concernant les membres de l'interface. J'ai reçu un avertissement concernant la propriété Attr de la classe C qui masque la propriété CReadOnly, mais cela devrait être entièrement attendu, car le masquage/l'ombrage est ce qui se passe dans mon exemple. Une chose étrange: je pourrais jurer que j'ai compilé (et couru!) Ce code plusieurs fois et j'ai vu 0 avertissements. Cela m'a troublé à l'époque, mais je l'ai laissé partir ... mais maintenant je vois l'avertissement comme je m'y attendais. Peut-être juste un pépin du compilateur.

1

Si vous souhaitez des attributs distincts portant le même nom, utilisez new. L'avertissement est explicite.

D'autre part, ce que vous voulez semble être plus comme:

#pragma warning disable CS0108 

interface IWithSet : I 
{ 
    int attr { get; set; } 
} 

#pragma warning restore CS0108 
+1

int attr {get; ensemble; } - warning: "'IWithSet.attr' cache le membre hérité 'I.attr' Utilisez le nouveau mot clé si le masquage était prévu." – SkyN

+0

Vous pouvez toujours forcer l'avertissement à être désactivé – sukru

+1

Vous devez faire attention à l'avertissement et faire ce qu'il dit, ne pas forcer les avertissements à être désactivés pour l'ensemble de votre interface. –

0

Peut-être pas parfait, mais une solution pourrait être:

interface IWithSet : I 
{ 
    void SetAttr(int value); 
} 
5

De C# Spécification: Les membres hérités d'une interface ne font pas spécifiquement partie de l'espace de déclaration de l'interface. Ainsi, une interface est autorisée à déclarer un membre avec le même nom ou la même signature qu'un membre hérité. Lorsque cela se produit, le membre d'interface dérivé est censé masquer le membre d'interface de base. Le masquage d'un membre hérité n'est pas considéré comme une erreur, mais le compilateur émet un avertissement. Pour supprimer l'avertissement, la déclaration du membre d'interface dérivé doit inclure un modificateur new pour indiquer que le membre dérivé est destiné à masquer le membre de base. (Interface members) La mise en œuvre correcte est:

interface IWithSet : I 
{ 
    new int attr { get; set; } 
} 
0

Que diriez-vous juste:

interface IWithSet : I 
{ 
    new int attr { get; set; } 
} 

L'inconvénient est IWithSet aura toujours à la fois getter et setter même si le getter dans 'I' est retirée:

interface I { } 

Si vous définissez la deux interfaces avec l'hypothèse que 'I' aura toujours le getter alors il n'y a rien de mal avec cette approche, cela fonctionnera bien dans une hiérarchie d'interface conçue pour restreindre l'accès plutôt que d'encapsuler une logique spécifique à une couche d'abstraction la structure de type écrivain où le wr iter hérite de tous les accès du lecteur sur l'hypothèse SAFE que le lecteur a l'autorisation de lecture!).