質問

.NET 4ベータ2には、 struct BigInteger を持つ新しいNumerics名前空間があります。 ドキュメントには、私が期待していたように、それは不変の型です。

しかし、ポストインクリメント演算子( ++ )に少し混乱しています。これは間違いなく値を変化させるようです。次の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オブジェクトは   不変、インクリメント演算子   その新しいBigIntegerオブジェクトを作成します   値はBigIntegerよりも1つ大きい   値で表されるオブジェクト。   したがって、Incrementの繰り返し呼び出し   高価かもしれません。

すべて問題なく、 b = b ++ を使用する必要がある場合は理解できたはずですが、値を変更するには ++ だけで十分です。

何か考えはありますか

役に立ちましたか?

解決

演算子 ++ および-は、通常の + および-演算子の観点から実装されています。現実には:

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 ...>

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

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

他のヒント

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

BigInteger temp=b;
b=temp+1;

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

BigInteger b = BigInteger.One;

b++;  // immutable ?

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

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

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

OK、しかしBigIntegerで定義されている単項否定演算子はどうですか:

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

不変性パターンを破り、BigIntegerオブジェクトを直接変異させるようです。だから

b = -b;

新しいオブジェクトを返すことなく、既存のBigIntegerを実際に変更します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top