web-dev-qa-db-ja.com

C#でのプリおよびポストインクリメント

C#コンパイラがプリおよびポストのインクリメントとデクリメントを処理する方法について少し混乱しています。

以下をコーディングする場合:

int x = 4;
x = x++ + ++x;

xはその後、値10になります。これは、プリインクリメントがx5に設定し、5+5に評価される10になるためだと思います。その後、ポストインクリメントはx6に更新しますが、10xに割り当てられるため、この値は使用されません。

しかし、私がコーディングするとき:

int x = 4;
x = x-- - --x;

その後、x2になります。誰がこれが事実なのか説明できますか?

61
Schweder

x--は4になりますが、--xの時点で3になるため、2になります。

x = 4 - 2

ところで、最初のケースはx = 4 + 6になります

以下に、各パーツの値を出力する小さな例を示します。おそらく、この方法でよりよく理解できます。

static void Main(string[] args)
{
    int x = 4;
    Console.WriteLine("x++: {0}", x++); //after this statement x = 5
    Console.WriteLine("++x: {0}", ++x); 

    int y = 4;
    Console.WriteLine("y--: {0}", y--); //after this statement y = 3
    Console.WriteLine("--y: {0}", --y);

    Console.ReadKey();
}

これは印刷されます

x++: 4
++x: 6
y--: 4
--y: 2
50
Sebastian Piu

そのステートメントから生成されるILを見てみましょう

IL_0002:  ldloc.0     

Xの値をスタックにロードします。スタック=>(4)

IL_0003:  dup         

スタックの一番上のアイテムを複製します。スタック=>(4、4)

IL_0004:  ldc.i4.1    

1をスタックにプッシュします。スタック=>(1、4、4)

IL_0005:  sub         

上位2つの値を減算し、結果をスタックにプッシュします。スタック=>(3、4)

IL_0006:  stloc.0     

スタックの最上位の値をxに戻します。スタック=>(4)

IL_0007:  ldloc.0     

Xの値をスタックにロードします。スタック=>(3、4)

IL_0008:  ldc.i4.1    

値1をスタックにロードします。スタック=>(1、3、4)

IL_0009:  sub         

2つを減算します。スタック=>(2、4)

IL_000A:  dup         

最上位の値を複製=>(2、2、4)

IL_000B:  stloc.0     

トップ値をxに戻します。スタック=>(2、4)

IL_000C:  sub      

上位2つの値を減算します。スタック=>(2)

IL_000D:  stloc.0  

この値をxに戻します。 x == 2

18
Mongus Pong

あなたのコメントから:

ポストインクリメントとプレインクリメントは、完全なコードラインの評価の前後に実行されると考えましたが、式の各項目の評価の前後に実行されます。

あなたの誤解は非常に一般的なものです。 Cなどの一部の言語では、副作用が目に見えるようになると指定されないため、Cではステートメントがtrueであることが正当ですが、必須ではないことに注意してください。

これはC#には当てはまりません。 C#式の左側のコードの副作用は、右側のコードが実行される前に常に発生することが観察されています(単一のスレッドから;マルチスレッドシナリオでは、すべての賭けはオフです。)

C#でインクリメント演算子が行うことの詳細については、以下を参照してください。

i ++と++ iの違いは何ですか?

このよく誤解されるトピックについて書いた記事への非常に多くの追加リンクがあります。

9
Eric Lippert

最も興味深いのは、C++。Netコンパイラでまったく異なる答えが得られることです。

int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1

もちろん、結果の違いは、異なるsemanticsによって決まります。これは正常なようです。しかし、2つの.netコンパイラがこのような基本的なことに対して同じような動作をしないという事実を理解しているにもかかわらず、私も混乱させられます。

6
Shymep

この例では、

int x = 4;
x = x++ + ++x;

次のように壊すことができます:

x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10

同様に、

int x = 4;
x = x-- - --x;

ここに、

x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2

単純に言えば、xの現在の値を置き換えることができますが、++または-ごとにxの値を加算/減算します。

2
Azhar Khorasany