web-dev-qa-db-ja.com

整数合計ブルー、短い+ =短い問題

C#のプログラム:

short a, b;
a = 10;
b = 10;
a = a + b; // Error : Cannot implicitly convert type 'int' to 'short'.

// we can also write this code by using Arithmetic Assignment Operator as given below

a += b; // But this is running successfully, why?

Console.Write(a);

ここで2つの質問があります。 1つ目は、「なぜintに短い結果と短い結果があるのか​​」です。

まあ、ショートプラスショートが短かったとし、何が起こるか見てみましょう。

short[] prices = { 10000, 15000, 11000 };
short average = (prices[0] + prices[1] + prices[2]) / 3;

もちろん、この計算がショートで行われる場合、平均は-9845です。合計が可能な最大のショートよりも大きいため、負に折り返してから、負の数を割ります。

整数演算がラップアラウンドする世界では、すべての計算をintで行う方がはるかに賢明です。これは、一般的な計算でオーバーフローしないように十分な範囲を持つ型です。

2番目の質問は次のとおりです。

  • ショートプラスショートはint
  • intをshortに割り当てることは違法です
  • a + = bはa = a + bと同じです
  • したがって、short + = shortは違法であるべきです
  • なぜこれが合法なのですか?

質問の前提が間違っています。上記の3行目が間違っています。 C#仕様はセクション7.17.2に記載されています

それ以外の場合、選択された演算子が事前定義された演算子であり、選択された演算子の戻り型が明示的にxの型に変換可能であり、yが暗黙的にxの型に変換可能であるか、演算子がシフト演算子である場合、操作x =(T)(x op y)として評価されます。ここで、Tはxのタイプですが、xは1回だけ評価されます。

コンパイラーがキャストを挿入します。正しい推論は次のとおりです。

  • ショートプラスショートはint
  • intをshortに割り当てることは違法です
  • s1 + = s2はs1 =(short)(s1 + s2)と同じです
  • したがって、これは合法であるべきです

キャストが挿入されなかった場合、多くのタイプで複合代入を使用することは不可能です。

71
Eric Lippert

さて、+=演算子は、aの値を短い値で増やすことになると言いますが、=は、次のようになりますoverwrite値と、操作の結果。操作 a + bは、他の方法で実行できることを知らずにintを生成し、そのintをshortに割り当てようとしています。

12
David Hedlund

使用する必要があります:

a = (short)(a + b);

割り当てと追加割り当ての動作の違いについては、これと何か関係があると思います(msdnから)

x+=y
is equivalent to
x = x + y
except that x is only evaluated once. The meaning of the + operator is
dependent on the types of x and y (addition for numeric operands, 
concatenation for string operands, and so forth).

ただし、少しあいまいなので、理解を深めたマビーがコメントできます。

9
UpTheCreek

これは、intが+が定義されている最小の符号付き型であるためです。小さいものは最初にintに昇格されます。 +=演算子は+に関連して定義されていますが、ターゲットに適合しない結果を処理するための特殊なケースルールが使用されています。

7
Marcelo Cantos

これは、+ =がオーバーロードされた関数として実装されているためです(その1つはshortであり、コンパイラーは最も具体的なオーバーロードを選択します)。式(a + b)の場合、コンパイラーはデフォルトで結果をintに広げてから割り当てます。

1
Stefan Mai