6
votes

Pouvez-vous utiliser le nouveau mot-clé C # pour développer les propriétés sur une interface?

Je comprends comment le mot-clé "nouveau" peut masquer des méthodes dans une classe dérivée. Cependant, quelles implications ont-elles pour les classes qui impliquent des interfaces qui utilisent le mot-clé?

considèrent cet exemple, où je décide d'élargir une interface en faisant sa lecture / écriture de propriétés. P>

public IReadOnly SomeMethod() {
   // return an instance of ICanReadAndWrite
}


5 commentaires

Votre exemple spécifique n'a pas beaucoup de sens. Si vous pouvez lire et écrire, alors ce n'est pas à la fois.


Un ishoppingcartitemreadreadrite peut être changé, mais si j'ai une référence à une ishoppingcartitemreadonly, il est en lecture seule à moins que vous ne le laissiez à autre chose.


Notez que vous n'avez pas besoin du mot-clé «Nouveau».


Qu'est-ce que le "nouveau" mot clé a à voir avec tout cela?


Je soupçonne que de meilleurs noms pour votre type seraient "lisibles" et "immuables".


5 Réponses :


0
votes

Je ne suis pas sûr que cela compile ou non, mais ce n'est pas un modèle souhaitable à suivre. Avec la possibilité de faire de la mise en œuvre explicite de l'interface, vous pouvez fournir théoriquement deux implémentations entièrement différentes pour le iReadonly et icanreadandwrite VERSION de la propriété ID . Envisagez de modifier l'interface iCanReadAndWrite en ajoutant une méthode de setter pour la propriété plutôt que de remplacer la propriété.


3 commentaires

Cela compile définitivement. Si vous n'ajoutez pas le nouveau mot-clé, vous obtenez la compilation suivante AVERTISSEMENT: 'ICANREADADANDWRITE.ID' HIDES HIDES HÉMÉDITÉ «IREADONLY.ID». Utilisez le nouveau mot-clé si la cache était destinée.


En ce qui concerne la mise en œuvre explicite de l'interface, je suppose que si vous le faites, deux implémentations entièrement différentes de la propriété ID correspond exactement à ce que vous voudriez. Je suis plus intéressé par les gotchas cachés ou des problèmes moins que évidents pouvant être causés par cette approche.


Malheureusement, il suffit d'ajouter un setter à la propriété ne fonctionnera pas. Si les ombres de réglage, la lecture de la propriété nécessite un typasty sur le type avec le getter non ombragé. Si le setter n'hédit pas le getter, c'est-à-dire un getter et un réglage indépendant de la portée, ils seront utilisables dans le C # ou VB.NET.



19
votes

Ce n'est pas une idée particulièrement mauvaise. Vous devez savoir que la mise en œuvre peut forte> (s'il implique implicitement l'interface, une seule propriété de lecture / écriture pourrait satisfaire à la fois des interfaces) fournit deux implémentations distinctes:

class Test : ICanReadAndWrite {
   public string Id {
      get { return "100"; }
      set { }
   }
   string IReadOnly.Id {
      get { return "10"; }
   }
}

Test t = new Test();
Console.WriteLine(t.Id);  // prints 100
Console.WriteLine(((IReadOnly)t).Id); // prints 10


5 commentaires

Bon point sur la silence de l'avertissement du compilateur! Cependant, il se plaint car faire quelque chose comme ceci pour que les définitions de classe puisse leur faire se comporter de manière à ne pas vous attendre. Pour ce cas particulier, je ne peux penser à aucun comportement involontaire ... D'où la question.


Oui. Bien sûr, l'avertissement est pour une raison. Comme je l'ai dit dans la réponse, le seul possible Gotcha est, comme je l'ai dit dans la réponse, le fait que vous ayez affaire à deux créneaux de méthode distincts pouvant être résolus à différentes implémentations. C'est le piège d'utilisation nouveau . Pour Interfaces Il n'est pas nocif la plupart du temps car ils ne fournissent aucune implémentation et que l'appelant s'attend à une mise en œuvre arbitraire de la méthode de toute façon.


Le nouveau mot-clé ne fait pas de silencer le compilateur, il est clairement indiqué que "Je ne veux pas remplacer d'un député, mon intention est de l'ombre, et je suis au courant du fait". L'avertissement est de vous empêcher de "cacher involontairement un membre".


Oui, et comme je l'ai mentionné dans un commentaire ci-dessous, je m'attendrais à une classe qui implémente explicitement les deux interfaces pour avoir une raison de le faire.


@Pop Catalin: Le point est de mentionner Nouveau n'affecte pas la génération de code. C'est le comportement par défaut (ce qui n'est pas le cas pour de remplacement ).



1
votes

Ceci est parfaitement légal et les implications pour votre classe qui implémentent l'interface ICANReadWeWrite serait simplement que, lorsqu'elle est traitée comme une ironie, elle ne peut que lire, mais lorsqu'il est traité comme icanreadandwrite, il serait capable de faire les deux.


0 commentaires

0
votes

Vous pouvez le faire, mais je ne suis pas sûr de ce que vous espérez accomplir en le faisant.

public interface IReadOnly
{
    String GetId();
}

public interface ICanReadAndWrite : IReadOnly
{
    String SetId();
}


1 commentaires

Je voudrais utiliser une propriété simple.



7
votes

Vous ne devez pas implémenter le cyanreadwrite en fonction de Ireadonly, mais les faire séparer.

IE. comme ceci: xxx

voici une classe en utilisant: xxx

Notez que la même propriété de la classe peut prendre en charge les deux Interfaces.

Notez que, selon le commentaire, le seul moyen d'obtenir une solution robuste serait également d'avoir un objet wrapper.

En d'autres termes, ce n'est pas bon: < / p> xxx

car l'appelant peut simplement faire ceci: xxx

Pour obtenir une solution robuste, vous avez besoin d'un objet wrapper, comme Ceci: xxx

Cela fonctionnera et être robuste, jusqu'à ce que l'appelant utilise la réflexion.


5 commentaires

Mais alors vous ne pouvez pas être jeté d'un ICANReadAndwrite à un iradonly. Ceci est très utile lorsque vous avez une classe qui fonctionne avec des objets en lecture / écriture, puis souhaitez que vous souhaitiez retourner un objet en lecture seule au consommateur.


Le consommateur peut tout simplement être renvoyé. Ce n'est pas robuste.


Bien sûr, ce n'est pas robuste, mais non plus la solution d'origine, si elle avait fonctionné. Le seul moyen de se débarrasser de la navette consiste à renvoyer un objet d'emballage qui l'empêche explicitement, c'est-à-dire. implémente uniquement irréfléchi.


Premièrement, le code de ma question initiale compile et travaille. Et il est assez robuste ... si vous avez baissé un type, vous feriez mieux de savoir ce que vous faites. +1 Pour la note sur un wrapper en lecture seule, cependant.


Oui, désolé, j'avais trompé du code quand je l'ai collé au début, ce qui me conduit à croire qu'il y avait quelque chose qui ne va pas avec le code. C'était ma faute, cependant, mais je laisserai le commentaire.