92 votes

Les paramètres peuvent-ils être constants?

Je cherche l'équivalent de final en Java en C#. Est-ce que ça existe?

Est-ce que C# a quelque chose comme ce qui suit:

public Foo(final int bar);

Dans l'exemple ci-dessus, bar est une variable en lecture seule et ne peut pas être modifiée par Foo(). Est-il possible de faire la même chose en C#?

Par exemple, peut-être que j'ai une longue méthode qui va travailler avec les coordonnées x, y et z d'un objet (des entiers). Je veux être absolument certain que la fonction ne modifie pas ces valeurs d'une manière qui corromprait les données. Ainsi, je voudrais les déclarer en lecture seule.

public Foo(int x, int y, int z) {
     // faire des trucs
     x++; // oups. Cela corrompt les données. Est-ce que cela peut être capté au moment de la compilation?
     // faire plus de trucs, en supposant que x est toujours la valeur initiale.
}

0 votes

Copie de stackoverflow.com/questions/2125591/… (et a une excellente réponse d'Eric Lippert, au fait)

12 votes

Je ne pense pas que ce soit un duplicata exact. Cette question concerne la différence entre la transmission par référence et la transmission par valeur. Je pense que Rosarch a peut-être utilisé un mauvais exemple de code pour le point qu'il essayait de faire passer.

0 votes

@Rosarch: De ce que je comprends du mot "final", c'est que vous ne pouvez plus agir sur l'objet, quel qu'il soit. Je comprends que "final" appliqué à une classe serait l'équivalent de "sealed" en C#. Mais quel est l'avantage ou l'utilisation réelle de ce mot-clé "final" de toute façon? Je l'ai presque toujours vu quelque part dans un code source JAVA.

65voto

Corey Sunwold Points 6330

Malheureusement, vous ne pouvez pas le faire en C#.

Le const mot clé ne peut être utilisé que pour les variables locales et les champs.

Le readonly mot clé ne peut être utilisé que sur les champs.

REMARQUE : Le langage Java supporte également la présence de paramètres finaux dans une méthode. Cette fonctionnalité est inexistante en C#.

de http://www.25hoursaday.com/CsharpVsJava.html

MODIFICATION (2019/08/13) : Je mentionne cela pour plus de visibilité car c'est accepté et en haut de la liste. C'est maintenant presque possible avec les paramètres in. Voirla réponse ci-dessous pour plus de détails.

1 votes

"Malheureusement"? En quoi cela différerait-il de la capacité actuelle?

34 votes

@John Saunders Malheureusement, car Rosarch cherche une fonctionnalité qui n'existe pas.

0 votes

@Corey : il recherche une fonction sans effet. Dans son exemple, le paramètre serait constant sans le const.

9voto

La réponse: le C# n'a pas la fonctionnalité constante comme le C++.

Je suis d'accord avec Bennett Dill.

Le mot-clé const est très utile. Dans l'exemple, vous avez utilisé un int et les gens ne comprennent pas votre point. Mais, que se passe-t-il si votre paramètre est un objet utilisateur énorme et complexe qui ne peut pas être modifié à l'intérieur de cette fonction ? C'est l'utilisation du mot-clé const : le paramètre ne peut pas changer à l'intérieur de cette méthode car [raison quelconque ici] cela n'a pas d'importance pour cette méthode. Le mot-clé const est très puissant et il me manque vraiment en C#.

8voto

Bennett Dill Points 1552

Voici une réponse courte et concise qui recevra probablement beaucoup de votes négatifs. Je n'ai pas lu tous les messages et commentaires, donc veuillez me pardonner si cela a déjà été suggéré auparavant.

Pourquoi ne pas prendre vos paramètres et les passer dans un objet qui les expose comme immutable, puis utiliser cet objet dans votre méthode?

Je réalise que c'est probablement une solution de contournement très évidente qui a déjà été envisagée et que l'auteur de la question essaie d'éviter en posant cette question, mais je pense qu'elle devrait être mentionnée quand même...

Bonne chance :-)

1 votes

Parce que les membres peuvent toujours être modifiés. Ce code c++ le montre : int* p; *p = 0;. Cela va se compiler et s'exécuter jusqu'à ce que l'erreur de segmentation se produise.

1 votes

J'ai voté négativement parce que ce n'est pas une solution au problème. Tu pourrais également enregistrer les arguments à l'en-tête de la fonction et les comparer à la fin, et déclencher une exception en cas de modification. Je vais garder ça dans ma poche arrière s'il y a jamais un concours de pire solution :)

7voto

Joel Coehoorn Points 190579

Je commencerai par la partie int. int est un type de valeur, et dans .Net cela signifie que vous traitez vraiment avec une copie. C'est une contrainte de conception vraiment bizarre de dire à une méthode "Tu peux avoir une copie de cette valeur. C'est ta copie, pas la mienne; je ne la reverrai plus. Mais tu ne peux pas changer la copie." C'est implicite dans l'appel de la méthode que copier cette valeur est autorisé, sinon nous ne pourrions pas avoir appelé la méthode en toute sécurité. Si la méthode a besoin de l'original, laissez à l'implémenteur le soin de faire une copie pour le sauvegarder. Donnez à la méthode la valeur ou ne lui donnez pas la valeur. Ne soyez pas indécis entre les deux.

Passons aux types de référence. Maintenant ça devient un peu confus. Voulez-vous dire une référence constante, où la référence elle-même ne peut pas être changée, ou un objet complètement verrouillé, immuable? Si c'est le premier cas, les références dans .Net sont passées par valeur par défaut. Autrement dit, vous obtenez une copie de la référence. Donc nous avons essentiellement la même situation que pour les types de valeur. Si l'implémenteur a besoin de la référence originale, il peut la conserver lui-même.

Cela nous laisse seulement avec un objet constant (verrouillé/immuable). Cela peut sembler acceptable d'un point de vue de l'exécution, mais comment le compilateur peut-il le faire respecter? Étant donné que les propriétés et les méthodes peuvent tous avoir des effets secondaires, vous seriez essentiellement limité à un accès en lecture seule des champs. Un tel objet n'est pas susceptible d'être très intéressant.

2 votes

J'ai voté négativement pour vous avoir mal compris la question; il ne s'agit pas de changer la valeur APRÈS l'appel, mais de la changer À L'INTÉRIEUR même.

2 votes

@silky - Je n'ai pas mal compris la question. Je parle aussi de l'intérieur de la fonction. Je dis que c'est une drôle de restriction d'envoyer à une fonction, car cela ne stoppe vraiment rien. Si quelqu'un oublie que le paramètre original a changé, il est tout aussi probable qu'il oublie qu'une copie a changé.

1 votes

Je ne suis pas d'accord. Fournir simplement un commentaire expliquant le vote négatif.

2voto

Hans Passant Points 475940

Si vous rencontrez souvent des problèmes comme celui-ci, vous devriez envisager la "notation hongroise" (aussi connue sous l'acronyme "apps hungarian"). La bonne sorte, contrairement à la mauvaise sorte. Bien que cela n'essaie généralement pas d'exprimer la constance d'un paramètre de méthode (c'est tout simplement trop inhabituel), rien ne vous empêche d'ajouter un "c" supplémentaire avant le nom de l'identifiant.

À tous ceux qui ont hâte de cliquer sur le bouton de vote négatif maintenant, veuillez lire les opinions de ces personnalités sur le sujet :

0 votes

Notez que vous n'avez pas besoin d'une convention de nommage pour appliquer cela ; vous pourriez toujours le faire avec un outil d'analyse après coup (ce n'est pas génial, mais néanmoins). Je crois que Gendarme (mono-project.com/Gendarme) a une règle pour cela, et probablement StyleCop/FxCop aussi.

0 votes

Facilement la pire tentative (échouée) de solution. Alors maintenant votre paramètre n'est pas seulement inscriptible, il vous met en échec en vous mentant sur le fait qu'il n'ait pas changé.

0 votes

Deux utilisateurs de SO souffrants jusqu'à présent, cela aurait pu être pire.

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