9

.NET 4ベータ2には、。を含む新しいNumerics名前空間があり struct BigIntegerます。ドキュメントには、私が予想したように、それは不変のタイプであると記載されています。

しかし、私はポストインクリメント演算子(++)に少し混乱しています。これは間違いなく値を変化させるようです。次のwhileループが機能します。

static BigInteger Factorial(BigInteger n)
{
    BigInteger result = BigInteger.One;
    BigInteger b = BigInteger.One;

    while (b <= n)
    {
        result = result * b;
        b++;  // immutable ?
    }
    return result;
}

これは、MSDNがインクリメント演算子について言っていることです。

BigIntegerオブジェクトは不変であるため、Increment演算子は、valueで表されるBigIntegerオブジェクトよりも値が1大きい新しいBigIntegerオブジェクトを作成します。したがって、Incrementを繰り返し呼び出すと、コストがかかる可能性があります。

うまくいっていれば、使用する必要があるかどうかは理解できたはずですが 、値を変更するにはb = b++、明らかにそれだけで十分です。++

何かご意見は?

4

5 に答える 5

14

演算子++--は、通常の演算子+と演算子の観点から実装されて-いるため、実際には次のようになります。

b++;

と同等です:

var temp = b;
b = b + 1;
<use temp for the expression where b++ was located>

さて、コメントしたように、これは不変性を壊すように見えるかもしれませんが、そうではありません。

代わりに、次のようにこのコードを確認する必要があります。

var temp = b;
b = BigInteger.op_Add(b, 1); // constructs a new BigInteger value
<use temp ...>

これにより、元のBigInteger値と、bによって参照される新しいオブジェクトの2つのオブジェクトがメモリに残ります。これが次のコードで発生することを簡単に確認できます。

var x = b;
b++;
// now inspect the contents of x and b, and you'll notice that they differ

したがって、元のオブジェクトは変更されなかったため、不変性が損なわれることはありません。質問の新しい部分に答えるには、これはスレッドセーフである必要があります。

これは、文字列に発生するのと同じことです。

String s1 = s2;
s2 += "More";
// now inspect s1 and s2, they will differ
于 2009-10-28T09:00:00.903 に答える
3

BigIntegerは不変であるため、b++は次と同等になります。

BigInteger temp=b;
b=temp+1;

この操作の後、温度はGCによってリサイクルされ、メモリが解放されます。

于 2009-10-28T09:05:31.570 に答える
0
BigInteger b = BigInteger.One;

b++;  // immutable ?

この例では、bは変数であり、現在のメソッドのスタックフレーム内のメモリのスロットにすぎません。これはOneに初期化され、b ++はbを受け取り、新しいBigInteger(増分値を含む)を作成して返します。変数bは、返された新しいBigIntegerからの状態になります。

正直なところ、概念としての不変性は、内部状態が決して変化しないオブジェクトがヒープ上にあるため、参照型を処理するときにはるかに明確になります。したがって、操作/メソッドが異なる状態の新しいオブジェクトを返す場合、それは一種の明白です(たとえば、 object.ReferenceEquals(object、object)を使用してオブジェクト参照の等価性チェックを実行できます。

値型の場合、ヒープ上にオブジェクトはなく、値であるビットを含むメモリ内のスロットのみがあります。

于 2019-03-22T13:55:44.040 に答える
-1

わかりましたが、BigIntegerで定義されている単項否定演算子についてはどうでしょうか。

public static BigInteger operator -(BigInteger value)
{
    value._sign = -value._sign;
    return value;
}

不変性パターンを破り、BigIntegerオブジェクトを直接変更しているように見えます。それで

b = -b;

実際には、新しいオブジェクトを返さずに、既存のBigIntegerを変更します。

于 2019-03-22T13:31:35.813 に答える
-1

マイクロソフトのドキュメントから、++について話した直後:
この例は既存のオブジェクトの値を変更しているように見えますが、そうではありません。
BigIntegerオブジェクトは不変です。つまり、内部的に、共通言語ランタイムは実際に新しいBigIntegerオブジェクトを作成し、以前の値より1つ大きい値を割り当てます。次に、この新しいオブジェクトが呼び出し元に返されます。

于 2020-04-05T15:55:24.010 に答える