Je les ai vus à la fois utilisé dans de nombreux morceaux de code C#, et j'aimerais savoir quand utiliser i++
ou ++i
(i
étant un nombre variable comme int
, float
, double
, etc). Toute personne qui le sait?
Réponses
Trop de publicités?La réponse typique à cette question, malheureusement déjà posté ici, est que l'on ne l'incrément "avant", le reste de ses opérations et l'autre ne l'incrément "après" d'autres opérations. Bien qu'intuitivement a l'idée de diamètre, qui est de l'instruction sur le visage de celui-ci complètement faux. La séquence des événements dans le temps est extrêmement bien défini en C#, et il n'est absolument pas le cas que le préfixe et le suffixe versions de ++ de faire les choses dans un ordre différent par rapport à d'autres opérations.
Il n'est pas surprenant que vous verrez beaucoup de mauvaises réponses à cette question. Un grand nombre de "teach yourself C#" livres aussi se tromper. En outre, le C# elle est différente de celle du C a-t-il. Beaucoup de gens de raison, comme si C# et C sont dans la même langue; ils ne le sont pas. La conception de l'incrémentation et de décrémentation les opérateurs en C#, à mon avis, évite les défauts de conception de ces opérateurs en C.
Il ya deux questions qui doivent être traitées afin de déterminer ce qu'est exactement le fonctionnement du préfixe et le suffixe ++ en C#. La première question est quel est le résultat? et la deuxième question est de savoir quand les effets secondaires de l'incrément?
Il n'est pas évident que la réponse à une question, mais il est en fait assez simple une fois que vous le voyez. Permettez-moi de préciser pour vous exactement ce que x++ et ++x faire pour une variable x.
Pour le préfixe de la forme:
- x est évalué à produire de la variable
- la valeur de la variable est copiée vers un emplacement temporaire
- la valeur temporaire est incrémenté pour produire une nouvelle valeur (de ne pas écraser le temporaire!)
- la nouvelle valeur est stockée dans la variable
- le résultat de l'opération est la nouvelle valeur
Pour postfix forme:
- x est évalué à produire de la variable
- la valeur de la variable est copiée vers un emplacement temporaire
- la valeur temporaire est incrémenté pour produire une nouvelle valeur (de ne pas écraser le temporaire!)
- la nouvelle valeur est stockée dans la variable
- le résultat de l'opération est la copie temporaire
Certaines choses sont à remarquer:
Tout d'abord, l'ordre des événements dans le temps, c'est exactement la même dans les deux cas. Encore une fois, il n'est absolument pas le cas, que l' ordre des événements dans le temps les changements entre le préfixe et le suffixe. Il est entièrement faux de dire que l'évaluation qui se passe avant d'autres évaluations ou après d'autres évaluations. Les évaluations se produire dans exactement le même ordre dans les deux cas. La seule différence est la dernière étape - si le résultat est la copie temporaire de la valeur d'origine, ou la nouvelle valeur.
Vous pouvez facilement le démontrer:
static class X
{
public static void M(this int x)
{
Console.WriteLine(C.c);
Console.WriteLine(x);
}
}
class C
{
public static int c = 0;
public static void Main()
{
(c++).M();
}
}
Les gens vont essayer de vous dire que l'accroissement du C.c
qui se passe après l'appel à l' X.M()
, mais comme vous pouvez le voir lorsque vous exécutez ce programme, il arrive avant l'appel à X.M()
. D'abord la valeur courante de C.c
est stocké dans un fichier temporaire, puis C.c
est incrémenté, et ensuite la valeur de la temporaire est passé de X.M()
. Si l'incrément est arrivé après l'appel à l' X.M()
alors il faudrait écrire la même valeur à deux reprises, mais il ne le fait pas.
Deuxièmement, c'est pas le cas que la valeur du préfixe version est la nouvelle valeur de x. C'est la valeur qui est stockée dans x. x n'est pas encore lire. x pourrait être volatile et changeante sur un autre thread; la valeur retournée par x++ est pas la valeur actuelle de x, c'est ce que x a été affectée, et qui pourrait être différent.
Il est étonnamment commun pour les gens à être très confus au sujet de la préséance, associativité, et l'ordre dans lequel les effets secondaires sont exécutés, je soupçonne surtout parce qu'il est si confus dans C. C# a été soigneusement conçu pour être le moins perturbant dans tous ces domaines. Pour une analyse complémentaire de ces questions, y compris de plus en plus loin en démontrant la fausseté de l'idée que le préfixe et le suffixe des opérations de "déplacer des choses autour de dans le temps", voir:
http://blogs.msdn.com/b/ericlippert/archive/2009/08/10/precedence-vs-order-redux.aspx
qui a conduit à cette DONC, la question:
int[] arr={0}; int valeur = arr[arr[0]++]; Valeur = 1?
Vous pourriez également être intéressé dans mes précédents articles sur le sujet:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/23/precedence-vs-associativity-vs-order.aspx
et
http://blogs.msdn.com/b/ericlippert/archive/2007/08/14/c-and-the-pit-of-despair.aspx
et un cas intéressant où C ce qui rend difficile de raisonner sur l'exactitude:
http://blogs.msdn.com/b/ericlippert/archive/2005/04/28/bad-recursion-revisited.aspx
Aussi, nous nous heurtons à de semblables questions subtiles lors de l'examen d'autres activités qui ont des effets secondaires, tels que les enchaînés des tâches simples:
Et voici un post intéressant sur les raisons de l'accroissement des opérateurs suite à valeurs dans C# plutôt que dans des variables:
Bizarrement il ressemble à l'autre des deux réponses n'est pas le préciser, et c'est certainement la peine de dire:
i++
moyen de me parler de la valeur de i
, puis incrémentation
++i
signifie 'increment i
, alors dites-moi la valeur"
Ils sont Pré-incrémentation, la post-incrémentation des opérateurs. Dans les deux cas, la variable est incrémentée, mais si vous prenez de la valeur de deux expressions exactement dans le même cas, le résultat sera différent.
Si vous avez:
int i = 10;
int x = ++i;
ensuite, x
sera 11
.
Mais si vous avez:
int i = 10;
int x = i++;
ensuite, x
sera 10
.
Note Eric points, l'incrément se produit en même temps dans les deux cas, mais c'est ce que la valeur donnée est le résultat qui diffère (merci Eric!).
En général, j'aime utiliser ++i
moins qu'il y ait une bonne raison de ne pas. Par exemple, lors de l'écriture d'une boucle, j'aime utiliser:
for (int i = 0; i < 10; ++i) {
}
Ou, si j'ai juste besoin d'incrémenter une variable, j'aime utiliser:
++x;
Normalement, d'une manière ou l'autre n'a pas beaucoup de signification et descend de style de codage, mais si vous êtes en utilisant les opérateurs à l'intérieur d'autres affectations (comme dans mes exemples), il est important d'être conscient des effets secondaires potentiels.
La façon dont l'opérateur fonctionne, c'est qu'il est incrémenté dans le même temps, mais si c'est devant un varable, l'expression d'évaluer avec le incrémenté/décrémenté variable:
int x = 0; //x is 0
int y = ++x; //x is 1 and y is 1
Si c'est après la variable dans l'instruction en cours seront exécutés avec la variable d'origine, comme si elle n'avait pas encore été incrémenté/décrémenté:
int x = 0; //x is 0
int y = x++; //'y = x' is evaluated with x=0, but x is still incremented. So, x is 1, but y is 0
Je suis d'accord avec dcp dans l'utilisation de pré-incrémentation/décrémentation (++x) sauf si nécessaire. Vraiment la seule fois que j'utilise la post-incrémentation/décrémentation est dans les boucles while ou des boucles de la sorte. Ces boucles sont les mêmes:
while (x < 5) //evaluates conditional statement
{
//some code
++x; //increments x
}
ou
while (x++ < 5) //evaluates conditional statement with x value before increment, and x is incremented
{
//some code
}
Vous pouvez aussi le faire lors de l'indexation des tableaux et tel:
int i = 0;
int[] MyArray = new int[2];
MyArray[i++] = 1234; //sets array at index 0 to '1234' and i is incremented
MyArray[i] = 5678; //sets array at index 1 to '5678'
int temp = MyArray[--i]; //temp is 1234 (becasue of pre-decrement);
Etc, etc...