BigInteger是不可变的吗?

时间:2009-10-28 08:54:53

标签: c# .net immutability biginteger fcl

在.NET 4 beta 2中,新的Numerics命名空间带有struct BigIntegerdocumentation表示它是一个不可变类型,正如我所期望的那样。

但我对后增量运算符(++)感到有些困惑。这种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;
}

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

  

因为BigInteger对象是   不可变,Increment运算符   创建一个新的BigInteger对象   value比BigInteger多一个   由价值代表的对象。   因此,反复调用Increment   可能很贵。

一切都很好,我会理解我是否必须使用b = b++,但显然++本身足以改变一个值。

有什么想法吗?

5 个答案:

答案 0 :(得分: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引用的新对象。您可以轻松地检查这是以下代码所发生的情况:

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

答案 1 :(得分:3)

由于BigInteger是不可变的,因此b ++将等同于:

BigInteger temp=b;
b=temp+1;

执行此操作后,GC将回收temp并释放内存。

答案 2 :(得分:0)

BigInteger b = BigInteger.One;

b++;  // immutable ?

在您的示例中,b是一个变量,它只是当前方法的堆栈框架中的一个内存插槽。它初始化为One,b ++接受b,创建一个新的BigInteger(具有递增的值)并返回它。变量b现在具有返回的新BigInteger的状态。

说实话,作为一个概念,不变性在处理引用类型时要更加清楚,因为堆上有一个对象,其内部状态永远不会改变,因此当操作/方法返回状态不同的新对象时,这很明显(例如,您可以使用object.ReferenceEquals(object,object)进行对象引用相等性检查。

对于值类型,堆上没有对象,内存中只有包含该值位的插槽。

答案 3 :(得分:-1)

好的,但是在BigInteger上定义的一元求反运算符呢?

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

它似乎打破了不变性模式,并直接使BigInteger对象突变。所以

b = -b;

实际上在不返回新对象的情况下更改了现有的BigInteger。

答案 4 :(得分:-1)

Microsoft文档,就在他们谈论++之后:
尽管此示例似乎修改了现有对象的值,但事实并非如此。
BigInteger对象是不可变的,这意味着公共语言运行库实际上在内部创建了一个新的BigInteger对象,并为其分配了一个更大的值。比之前的值高。然后,这个新对象将返回给调用者。