BigInteger是不可变的吗?

Hen*_*man 9 .net c# biginteger immutability fcl

在.NET 4 beta 2中,有一个新的Numerics命名空间 struct BigInteger.该文件指出,这是一个不变的类型,因为我本来期望.

但我对后增量运算符(++)有点困惑.这种defintely似乎改变了价值.以下while循环有效:

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

    while (b <= n)
    {
        result = result * b;
        b++;  // immutable ?
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

这就是MSDN对Increment运算符的看法:

因为BigInteger对象是不可变的,所以Increment运算符创建一个新的BigInteger对象,其值比value表示的BigInteger对象多一个.因此,重复调用Increment可能很昂贵.

一切都很好,我会理解,如果我必须使用, b = b++但显然++本身就足以改变一个价值.

有什么想法吗?

编辑:
正如Lasse所指出的那样,对增量后工作的方式有一个逐步的说明.但这仍然似乎与不变性有关.例如,我无法想象使用此运算符是线程安全的.

ang*_*son 14

运营商++--以正常的条款实施+-运营商,因此在现实中:

b++;
Run Code Online (Sandbox Code Playgroud)

相当于:

var temp = b;
b = b + 1;
<use temp for the expression where b++ was located>
Run Code Online (Sandbox Code Playgroud)

现在,正如评论所说,这似乎打破了不变性,但事实并非如此.

您应该将此代码视为执行此操作:

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

这将在内存中保留两个对象,即原始BigInteger值,以及现在由b引用的新对象.您可以轻松地检查这是以下代码所发生的情况:

var x = b;
b++;
// now inspect the contents of x and b, and you'll notice that they differ
Run Code Online (Sandbox Code Playgroud)

所以原始对象没有改变,因此它不会破坏不变性,并且回答问题的新部分,这应该是线程安全的.

这与字符串相同:

String s1 = s2;
s2 += "More";
// now inspect s1 and s2, they will differ
Run Code Online (Sandbox Code Playgroud)

  • 在`s + = s2`中有一个可见的赋值.如果你接受`b ++`也是一个赋值,即`b = b + 1`,它就适合.但是`++`仍然感觉/看起来像是在变异. (2认同)