7
votes

Est-il possible de faire "ce type" pour les génériques en C #?

type de question théorique. Assez longtemps, n'hésitez pas à passer si vous n'êtes pas d'humeur à la théorie.

Imaginez que vous avez deux classes, une héritée d'une autre. La classe de base est générique et dispose d'une méthode qui, dans le type fermé, doit renvoyer une instance de ce type fermé.

comme ceci (note ??? dans le texte): xxx

Je ne peux pas le faire car il n'y a pas de façon de se référer à un type fermé qui sera dérivé d'un type générique. (Désolé pour la langue brisée, je ne sais tout simplement pas comment l'exprimer.) Il n'y a pas de mot clé à définir à la place de ??? pour spécifier que cette méthode retournera l'instance de type qui serait dérivée de ce type générique.

Au lieu de cela, je peux utiliser une solution de contournement de transmettre explicitement le nom de type à la base générique. Mais il a l'air redondant. xxx

et si dans la classe de base, j'ai besoin d'accéder aux membres de This instance, je dois ajouter une contrainte. Cette fois, il a l'air laidly - Notez la contrainte: xxx

Oui, tout fonctionne, mais cela aurait l'air mieux si je peux simplement utiliser un mot-clé plutôt que ? ?? dans le premier fragment de code. Quelque chose comme " ce type ".

Comment pensez-vous qu'il fonctionnera? Est-ce utile? Ou peut-être que c'est tout simplement stupide?


0 commentaires

4 Réponses :


5
votes

Vous voudrez normalement simplement référence à la classe de base dans ce cas:

public class Adapter<T> { 
   public virtual Adapter<T> DoSomething();


5 commentaires

Il semble que c'était la réponse parfaite ici: Stackoverflow.com/questions/1400317


Oui, mais ce n'est pas le même scénario. Ils ne fonctionnent pas d'une classe de base, mais plutôt d'un type concret.


Non, roseau ceci ne fonctionnera pas, car je veux que ce type de type dérivé (fermé) puisse retourner AdapdeString, ce n'est pas ce type de base.


Et je ne suis pas d'accord pour violer le principe de Liskov. Notre classe de base est ouverte. De toute façon, nous ne pouvons pas écrire du code contre celui-ci, de sorte que des types dérivés n'ont tout simplement rien à casser.


XOR: Si c'est le cas, cela fonctionne bien. Il suffit de ne pas l'ajouter à votre classe de base. La classe de béton peut avoir cette méthode. Cependant, si vous l'ajoutez à la classe de base, il viole le LSP



-2
votes

Si une méthode héritée de votre classe dérivée doit renvoyer le type dérivé au lieu du type de base (appelé type de retour covariant ), ceci est déjà pris en charge en C #.


2 commentaires

Non, parce que c # ne prend pas en charge les types de retour covariant.


(Et même si cela le faisait, cela ne serait toujours pas toujours suffisant pour aider.)



15
votes

Il n'y a rien qui rend ce modèle plus facile et, en fait, le motif n'est pas assez pare-balles de toute façon - parce que vous pouvez avoir: xxx

la deuxième ligne ici est entièrement légal - Typea est un argument de type valide pour le paramètre tthis This, même si ce n'est pas ce que nous voulions. Fondamentalement, le système de type ne nous permet pas d'exprimer le concept de "T" doit être ce type. "

Je suis en désaccord avec ceux qui disent que c'est un modèle mauvais ou inutile, cependant. J'ai trouvé cela utile (si compliqué) dans Tampons de protocole - qui serait Soyez beaucoup pire sans elle. Par exemple: xxx

ne fonctionnerait pas si foo.build () n'a pas été fortement tapé pour retourner foo , Même si la méthode est spécifiée dans ibuilder <...> .

Ça mérite d'éviter cela si vous êtes facilement simplement parce que cela devient tellement compliqué - mais je pense que c'est un modèle utile de savoir.


2 commentaires

Jon, deuxième ligne dans votre exemple n'est que quelque chose de différent, ce qui ne tombe pas dans ce motif. Si cela est nécessaire quelque part, il peut être atteint par la syntaxe existante. Je pense juste que cette syntaxe rend les choses dans mon exemple encore plus compliquées. J'ai écrit ce post après avoir trouvé un bogue dans notre code. J'ai écrit cette classe de base au début il y a quelque temps, mais je devais la relire plusieurs fois pour obtenir une adhérence à nouveau. Pas étonnant que d'autres gars ont introduit un bug.


@XOR: Mon point est que la deuxième ligne est légale mais indésirable (dans ce cas). Je vais éditer la réponse pour rendre cela plus clair.



-2
votes

Moi aussi j'ai du mal à trouver un cas d'utilisation discutable pour cela (bien que ce soit une idée intéressante).

essayez-vous de vous déplacer sur la façon dont vous contraindrez quels types génériques que vous pouvez utiliser? On dirait que vous voulez supposons une fonctionnalité de base sans connaître le type actuel; C'est ce que sont les interfaces pour strong>. La clause WHERE est plutôt pratique pour ces types de problèmes. P>

class Dictionary<K, V>
where K : IComparable, IEnumerable
where V : IMyInterface
{
    public void Add(K key, V val)
    {
    }
}


0 commentaires