43 votes

Pourquoi les génériques C# ne peuvent-ils pas dériver d'un des paramètres de type générique comme c'est le cas dans les modèles C++ ?

Pourquoi les génériques C# ne peuvent-ils pas dériver d'un des paramètres du type générique comme ils peuvent le faire dans les templates C++ ? Je veux dire que je sais que c'est impossible parce que le CLR ne le supporte pas, mais pourquoi ?

Je suis conscient des différences profondes entre les modèles C++ et les génériques C# - les premiers sont des entités de compilation et doivent être résolus pendant la compilation, tandis que les seconds sont des entités d'exécution de première classe.

Pourtant, je ne vois pas la raison Les concepteurs du CLR n'ont pas mis au point un schéma permettant à un type générique du CLR de dériver de l'un de ses paramètres de type générique. Après tout, ce serait une fonctionnalité extrêmement utile, qui me manque personnellement beaucoup.

EDIT :

J'aimerais connaître l'existence d'un problème grave, dont la résolution entraînerait un prix si élevé pour la mise en œuvre de cette fonctionnalité qu'il justifierait qu'elle ne soit pas encore mise en œuvre. Par exemple, examinez cette déclaration fictive :

class C<T> : T
{
}

Comme l'a remarqué Eric Lippert, que se passerait-il si " Et si T est un struct ? Et si T est un type de classe scellée ? Et si T est un type d'interface ? Et si T est un C ? Et si T est une classe dérivée de C ? Et si T est un type abstrait avec une méthode abstraite ? Et si T a moins d'accessibilité que C ? Et si T est System.ValueType ? (Peut-on avoir une non-structure qui hérite de System.ValueType ?) Qu'en est-il de System.Delegate, System.Enum, et ainsi de suite ? "

Comme le poursuit Eric, " Ce sont les plus faciles, les plus évidentes ". En effet, il a raison. Ce qui m'intéresse, c'est un exemple concret d'une question ni facile ni évidente, qui est difficile à résoudre.

62voto

Eric Lippert Points 300275

Eh bien, commencez par vous demander ce qui pourrait bien aller mal avec class C<T> : T { } . Un grand nombre de choses me viennent immédiatement à l'esprit :

Et si T est un struct ? Et si T est un type de classe scellée ? Et si T est un type d'interface ? Et si T est C<T> ? ! Et si T est une classe dérivée de C<T> ? Et si T est un type abstrait avec une méthode abstraite ? Et si T a moins d'accessibilité que C ? Et si T est System.ValueType ? (Peut-on avoir une non-structure qui hérite de System.ValueType ?) Qu'en est-il de System.Delegate, System.Enum, et ainsi de suite ?

Ce sont les plus faciles, les plus évidentes. La fonctionnalité proposée ouvre littéralement des centaines, voire des milliers de questions plus subtiles sur l'interaction entre le type et son type de base, qui devront toutes être soigneusement spécifiées, implémentées et testées. Il ne fait aucun doute que nous en manquerions certaines, ce qui entraînerait des changements radicaux à l'avenir ou imposerait au moteur d'exécution un comportement défini par l'implémentation.

Les coûts seraient énormes, donc le bénéfice a intérêt à être énorme. Je ne vois pas d'énorme bénéfice ici.

34voto

Eric Lippert Points 300275

OK, si vous n'avez pas aimé ma réponse précédente, alors prenons un autre chemin.

Votre question présuppose une fausseté : que nous avons besoin d'une raison à pas mettre en œuvre une fonctionnalité. Au contraire, nous avons besoin d'une très, très bonne raison pour mettre en œuvre une fonctionnalité. Les fonctionnalités sont extrêmement coûteuses en termes de coûts initiaux, de coûts de maintenance et de coûts d'opportunité. (C'est-à-dire que le temps que vous passez sur la fonctionnalité X est du temps que vous ne pouvez pas passer à faire la fonctionnalité Y, et qui pourrait vous empêcher de faire un jour la fonctionnalité Z). Afin de fournir de la valeur à nos clients et à nos partenaires de manière responsable, nous ne pouvons pas mettre en œuvre toutes les fonctionnalités qui plaisent à quelqu'un.

Ce n'est pas aux concepteurs du runtime de justifier pourquoi ils n'ont pas implémenté une fonctionnalité que vous trouvez particulièrement intéressante. Les fonctionnalités sont classées par ordre de priorité en fonction de leurs coûts par rapport aux avantages pour les utilisateurs, et les utilisateurs n'ont pas exactement martelé ma porte pour demander ce type d'héritage. Cette fonctionnalité particulière changerait massivement la façon dont l'analyse du système de types fonctionne dans le runtime, aurait des effets considérables sur chaque langage qui utilise des génériques, et me semble apporter très peu d'avantages.

Nous utilisons ce type d'héritage dans le compilateur - écrit en C++ - et le code qui en résulte est difficile à suivre, à maintenir et à déboguer. J'ai fait de mon mieux pour éliminer progressivement ce type de code. Je suis opposé à l'activation du même genre de mauvais modèles en C#, à moins qu'il n'y ait un avantage énorme à le faire.

La tâche de décrire cet énorme avantage de manière convaincante incombe aux personnes qui veulent cette fonctionnalité, et non à celles qui devraient la mettre en œuvre. Quel est donc l'avantage convaincant ?

12voto

maliger Points 331

Exemple de code, où cela pourrait être utile :

public class SpecialDataRow<T> : T where T : DataRow
{
    public int SpecialFactor { get; set; }
}

Cela permettrait de créer des lignes "spéciales" à partir de DataRow et également à partir de toute ligne de données dérivée (comme les lignes générées par des ensembles de données typés).

Je ne vois pas d'autre moyen de coder une telle classe.

2voto

jalf Points 142628

Qu'est-ce qui serait si utile dans tout ça ?

N'oubliez pas que, malgré leur nom, les génériques n'ont jamais été conçus pour prendre en charge la programmation générique.

Pour prendre en charge une telle fonctionnalité, ils devraient apporter des changements assez importants au CLR.

Il faudrait définir une classe qui dérive d'un type qui n'existe même pas au moment de la compilation.

Pourquoi devraient-ils franchir de tels obstacles et compromettre fondamentalement leur système d'identification pour ajouter cette fonctionnalité ? Cela en vaut-il la peine ?

Si vous le pensez, dites-leur pourquoi. Écrivez un commentaire sur connect.microsoft.com pour leur dire pourquoi cette fonctionnalité est si fondamentale qu'elle doit être ajoutée.

1voto

Philippe Leybaert Points 62715

Les templates C++ ne peuvent être comparés aux génériques C#. Les modèles C++ sont prétraités comme des macros, tandis que les génériques dans .NET sont gérés par le runtime.

Mais il y a d'autres personnes qui en savent beaucoup plus que moi...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X