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 y a aussi d'autres raisons spécifiques au C ++, comme passer const ref
pour passer par ref et être sûr que l'état ne sera pas changé. 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)
{}
....
c#
language-agnostic
language-design
Incognito
la source
la source
Réponses:
En plus des autres bonnes réponses, j'ajouterai encore une autre raison pour laquelle ne pas mettre la constness de style C dans C #. Tu as dit:
Si const faisait ça, ce serait génial. 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 accepte une chose const. 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 prendre à la méthode un const. Qu'est-ce que les deux auteurs peuvent supposer est invariant pour l'objet?
Rien. L'appelé est libre de rejeter le const et de muter l'objet, de sorte que l'appelant n'a aucune garantie que l'appel d'une méthode qui prend un const ne le mute pas. 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é .
Le const de style C n'offre aucune garantie que l'objet ne changera pas et qu'il est donc cassé. Maintenant, C a déjà un système de type faible dans lequel vous pouvez réinterpréter le cast d'un double en un int si vous le souhaitez vraiment, il ne devrait donc pas être surprenant qu'il ait également un système de type faible par rapport à const. 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 types parce que nous ne voulons pas que le système de types soit un mensonge . Nous voulons que le système de typage soit fort pour que vous puissiez raisonner correctement sur votre code.
Const en C est une ligne directrice ; 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 types ; les éléments du système de types doivent être un fait sur l'objet sur lequel vous pouvez raisonner, et non un guide pour son utilisation.
Maintenant, ne vous méprenez pas; ce n'est pas parce que const en C est profondément brisé que tout le concept est inutile. Ce que j'aimerais voir, c'est une forme d'annotation "const" réellement correcte et utile 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 autres optimisations avancées.
Par exemple, imaginez si vous pouviez "dessiner une boîte" autour d'un morceau de code et dire "Je vous garantis que ce morceau de code n'effectue aucune mutation dans aucun 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 pas d'une manière qui soit observable en dehors de la boîte". Un tel objet ne peut pas être automatiquement multi- threadé en toute sécurité, mais il peut être mémorisé automatiquement . 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 bien mieux que la faible annotation const de style C.
Cependant, je souligne qu'il ne s'agit que de spéculation . Nous n'avons pas l'intention de mettre ce type de fonctionnalité dans une future version hypothétique de C #, s'il y en a 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 exiger, mais rien de tout cela ne devrait être interprété en aucune façon 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, et une erreur de compilation pour changer la méthode. La variable déclarée par l'instruction "using" est déjà un tel local; nous pourrions ajouter une annotation facultative à toutes les variables locales et paramètres pour les faire agir comme des variables "utilisant". Cela n'a jamais été une fonctionnalité très prioritaire, donc elle n'a jamais été implémentée.
la source
0xDEADBEEF
. Mais les deux seraient une très mauvaise programmation, et capturés tôt et de manière poignante par n'importe quel compilateur moderne. À l'avenir, lorsque vous rédigez des réponses, veuillez ne pas confondre ce qui est techniquement possible en utilisant les portes dérobées d'un langage avec ce qui est faisable dans le code réel. Des informations biaisées comme celle-ci déroutent les lecteurs moins expérimentés et dégradent la qualité des informations sur le SO.L'une des raisons pour lesquelles il n'y a pas de correction de const en C # est qu'elle 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 de notion de correction de const sont par exemple:
La correction des constats est à peu près une fonctionnalité de langage présente uniquement en C ++. Donc, cela revient à peu près à la même argumentation quant à la raison pour laquelle le CLR ne nécessite pas d'exceptions vérifiées (qui est une fonctionnalité du langage Java uniquement).
De plus, je ne pense pas que vous puissiez introduire une fonctionnalité de système de type aussi fondamentale dans un environnement géré sans rompre la compatibilité descendante. Donc, ne comptez pas sur l'exactitude de const entrant dans le monde C #.
la source
ref
paramètre (en particulier, dans le cas des méthodes / propriétés struct,this
). Si une méthode indique spécifiquement qu'elle n'écrira pas dans unref
paramètre, le compilateur doit autoriser la transmission de valeurs en lecture seule. Inversement, si une méthode déclare qu'elle va écrirethis
, le compilateur ne doit pas permettre à une telle méthode d'être appelée sur des valeurs en lecture seule.Je crois qu'il y a deux raisons pour lesquelles C # n'est pas constant.
Le premier est la compréhensibilité . Peu de programmeurs C ++ comprennent la correction de const. L'exemple simple de
const int arg
est mignon, mais j'ai aussi vuchar * const * const arg
- un pointeur constant vers des pointeurs constants vers des caractères non constants. La correction des constantes sur les pointeurs vers des fonctions est un tout nouveau niveau d'obfuscation.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 constness à gérer, sans syntaxe évidemment claire . Un point d'achoppement similaire concerne les collections (et les collections de collections, etc.).
Const-correctness 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 c'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.
la source
modopt
etmodreq
au niveau des métadonnées pour stocker ces informations (comme le fait déjà C + / CLI - voirSystem.Runtime.CompilerServices.IsConst
); et cela pourrait également être étendu aux méthodes const.const
signifie «constante à la 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 # estreadonly
, mais celui-ci n'est applicable qu'aux champs. En dehors de cela, il n'y a pas du tout de notion de correction de const dans C # semblable à C ++.La justification est difficile à dire avec certitude, car il y a beaucoup de raisons potentielles, mais je suppose que ce serait le désir de garder le langage simple avant tout, et les avantages incertains de la mise en œuvre de ce second.
la source
Cela est possible depuis C # 7.2 (décembre 2017 avec Visual Studio 2017 15.5).
Pour les structures et les types de base uniquement! , pas pour les membres des classes.
Vous devez utiliser
in
pour envoyer l'argument comme entrée par référence. Voir:Voir: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
Pour votre exemple:
la source