web-dev-qa-db-fra.com

Pourquoi les paramètres const ne sont-ils pas autorisés en C #?

Cela semble étrange, en particulier pour les développeurs C++. En C++, nous avions l'habitude de marquer un paramètre comme const afin d'être sûr que son état ne sera pas modifié dans la méthode. Il existe également d'autres raisons spécifiques au C++, comme le passage de const ref pour passer par ref et être sûr que cet état ne sera pas modifié. Mais pourquoi ne pouvons-nous pas marquer comme paramètres de méthode const en C #?

Pourquoi ne puis-je pas déclarer ma méthode comme suit?

    ....
    static void TestMethod1(const MyClass val)
    {}
    ....
    static void TestMethod2(const int val)
    {}
    ....
97
Incognito

En plus des autres bonnes réponses, j'ajouterai une autre raison pour ne pas mettre la constance de style C en C #. Tu as dit:

nous marquons le paramètre comme const afin d'être sûr que son état ne sera pas changé dans la méthode.

Si const le faisait, ce serait formidable. Const ne fait pas ça. Le const est un mensonge!

Const ne fournit aucune garantie que je puisse réellement utiliser. Supposons que vous ayez une méthode qui prend une chose constante. Il existe deux auteurs de code: la personne qui écrit l'appelant et la personne qui écrit l'appelé . L'auteur de l'appelé a fait en sorte que la méthode prenne une const. Qu'est-ce que les deux auteurs peuvent supposer invariant sur l'objet?

Rien. L'appelé est libre de rejeter le const et de muter l'objet, donc l'appelant n'a aucune garantie que l'appel d'une méthode qui prend un const ne mutera pas il. De même, l'appelé ne peut pas supposer que le contenu de l'objet ne changera pas tout au long de l'action de l'appelé; l'appelé pourrait appeler une méthode de mutation sur un alias non const de l'objet const, et maintenant le soi-disant objet const a changé .

La constante de style C ne garantit pas que l'objet ne changera pas et est donc cassé. Maintenant, C a déjà un système de type faible dans lequel vous pouvez réinterpréter le transtypage d'un double en un int si vous le voulez vraiment, donc il ne devrait pas être surprenant qu'il ait un système de type faible en ce qui concerne const également. Mais C # a été conçu pour avoir un bon système de type , un système de type où lorsque vous dites "cette variable contient une chaîne" que la variable contient en fait une référence à une chaîne (ou null). Nous ne voulons absolument pas mettre un modificateur "const" de style C dans le système de type parce que nous ne voulons pas que le système de type soit un mensonge . Nous voulons que le système de type soit fort afin que vous puissiez raisonner correctement à propos de votre code.

Const en C est une directive ; cela signifie essentiellement "vous pouvez me faire confiance pour ne pas essayer de muter cette chose". Cela ne devrait pas être dans le système de type ; la substance dans le système de type devrait être un fait sur l'objet qui vous pouvez raisonner, pas une directive à son utilisation.

Maintenant, ne vous méprenez pas; ce n'est pas parce que const en C est profondément rompu que le concept est inutile. Ce que j'aimerais voir, c'est une forme ( correcte et utile de annotation "const" en C #, une annotation que les humains et les compilateurs pourraient utiliser pour les aider à comprendre le code, et que le runtime pourrait utiliser pour faire des choses comme la paralellisation automatique et d'autres optimisations avancées.

Par exemple, imaginez si vous pouviez "dessiner une boîte" autour d'un morceau de code et dire "je garantis que ce morceau de code n'effectue aucune mutation champ de cette classe "d'une manière qui pourrait être vérifiée par le compilateur. Ou dessinez une boîte qui dit "cette méthode pure mute l'état interne de l'objet mais en aucune manière qui est observable en dehors de la boîte". Un tel objet ne peut pas être automatiquement multithread en toute sécurité mais il peut être automatiquement mémorisé . Il y a toutes sortes d'annotations intéressantes que nous pourrions mettre sur le code qui permettraient des optimisations riches et une compréhension plus profonde. Nous pouvons faire beaucoup mieux que l'annotation const faible de style C.

Cependant, je souligne qu'il ne s'agit que de spéculation . Nous n'avons pas l'intention ferme d'intégrer ce type de fonctionnalité dans une future version hypothétique de C #, s'il en existe une, que nous n'avons pas annoncée d'une manière ou d'une autre. C'est quelque chose que j'aimerais voir et quelque chose que l'accent à venir sur l'informatique multicœur pourrait nécessiter, mais rien de tout cela ne devrait être interprété comme une prédiction ou une garantie d'une fonctionnalité particulière ou d'une direction future pour C #.

Maintenant, si ce que vous voulez est simplement une annotation sur la variable locale qui est un paramètre qui dit "la valeur de ce paramètre ne change pas tout au long de la méthode", alors, bien sûr, ce serait facile à faire. Nous pourrions prendre en charge les paramètres locaux et les paramètres "en lecture seule" qui seraient initialisés une fois, ainsi qu'une erreur de compilation à modifier dans la méthode. La variable déclarée par l'instruction "using" est déjà un tel local; nous pourrions ajouter une annotation facultative à tous les paramètres locaux et paramètres pour les faire agir comme des "variables". Il n'a jamais été une fonctionnalité très prioritaire, il n'a donc jamais été implémenté.

59
Eric Lippert

L'une des raisons pour lesquelles il n'y a pas const correctness en C # est parce qu'il n'existe pas au niveau de l'exécution. N'oubliez pas que C # 1.0 n'avait aucune fonctionnalité sauf s'il faisait partie du runtime.

Et plusieurs raisons pour lesquelles le CLR n'a pas une notion d'exactitude const sont par exemple:

  1. Cela complique l'exécution; de plus, la JVM ne l'avait pas non plus, et le CLR a commencé comme un projet pour créer un runtime de type JVM, pas un runtime de type C++.
  2. S'il existe une constance correcte au niveau de l'exécution, il devrait y avoir une constance dans la BCL, sinon la fonctionnalité est à peu près inutile en ce qui concerne le .NET Framework.
  3. Mais si le BCL nécessite une correction constante, chaque langue au-dessus du CLR devrait prendre en charge la correction constante (VB, JavaScript, Python, Ruby, F #, etc.). C'est pas va arriver.

La correction des constantes est à peu près une fonctionnalité de langage uniquement présente en C++. Donc, cela revient à peu près à la même argumentation pour expliquer pourquoi le CLR ne nécessite pas d'exceptions vérifiées (qui est une fonction Java langue uniquement).

De plus, je ne pense pas que vous puissiez introduire une telle fonctionnalité de système de type fondamental dans un environnement géré sans rompre la compatibilité descendante. Alors ne comptez pas sur la constance de la constance dans le monde C #.

23
Ruben

Je crois qu'il y a deux raisons pour lesquelles C # n'est pas const-correct.

Le premier est compréhensibilité. Peu de programmeurs C++ comprennent la const-correct. Le simple exemple de const int arg est mignon, mais j'ai aussi vu char * const * const arg - un pointeur constant vers des pointeurs constants vers des caractères non constants. La constance des pointeurs vers les fonctions est un tout nouveau niveau d'obscurcissement.

La seconde est que les arguments de classe sont des références passées par valeur. Cela signifie qu'il y a déjà deux niveaux de constance à gérer, sans clairement évident syntaxe. Un point d'achoppement similaire est celui des collections (et des collections de collections, etc.).

La constance est une partie importante du système de type C++. Il pourrait - en théorie - être ajouté à C # comme quelque chose qui n'est vérifié qu'au moment de la compilation (il n'a pas besoin d'être ajouté au CLR, et n'affecterait pas le BCL à moins que la notion de méthodes membres const ne soit incluse) .

Cependant, je pense que cela est peu probable: la deuxième raison (syntaxe) serait assez difficile à résoudre, ce qui rendrait la première raison (compréhensibilité) encore plus problématique.

11
Stephen Cleary

const signifie "constante de compilation" en C #, pas "en lecture seule mais éventuellement modifiable par un autre code" comme en C++. Un analogue approximatif de C++ const en C # est readonly, mais celui-ci ne s'applique qu'aux champs. En dehors de cela, il n'y a pas du tout de notion similaire à C++ de const correct dans C #.

La justification est difficile à dire avec certitude, car il y a beaucoup de raisons potentielles, mais je suppose que le désir serait de garder le langage simple d'abord et avant tout, et les avantages incertains de la mise en œuvre de cette seconde.

5
Pavel Minaev