2009-10-28 5 views
9

В .NET 4 beta 2 существует новое пространство имен Numerics с struct BigInteger. В documentation указано, что это неизменный тип, как я и ожидал.Является ли BigInteger неизменным или нет?

Но я немного смущен оператором пост-инкремента (++). Очевидно, что это искажает ценность. Ниже в то время как петля работает:

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 являются неизменны, оператор инкремента создает новый объект BigInteger которого значение больше, чем объект BigInteger , представленный значением. Следовательно, повторные вызовы Increment могут быть дорогими.

Все хорошо и прекрасно, я бы понял, если бы я должен был использовать b = b++, но, по-видимому ++ само по себе достаточно, чтобы изменить значение.

Любые мысли?

Редактировать:
Как указывает Лассе, есть step-by-step specification, как работает пост-инкремент. Но это все еще кажется шансом с неизменностью. Например, я не могу себе представить, что использование этого оператора является потокобезопасным.

ответ

13

Операторы ++ и -- реализуются в терминах нормальных + и - операторов, так и в реальности:

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, а новый, теперь ссылается на Ь. Вы можете легко проверить, что это то, что происходит со следующим кодом:

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 
+0

Звучит разумно, но по-прежнему кажется, что он нарушает неизменность. Я немного отредактирую вопрос. –

+1

Нет, это не сломает неизменность, позвольте мне уточнить мой ответ. –

+2

В 's + = s2' есть видимое задание. Он подходит, если вы согласитесь, что 'b ++' также является присвоением, то есть 'b = b + 1'. Но '++' все еще чувствует/выглядит так, как будто он мутирует. –

3

С BigInteger неизменен, б ++ будет просто эквивалентно:

BigInteger temp=b; 
b=temp+1; 

После этой операции температура перерабатывается на GC и память освобождается.

+1

OK, за исключением части GC. Это структура (с внутренним массивом). –

+0

Да, и единственное отличие состоит в том, что структура хранится в стеке, пока этот класс хранится в куче. –

+0

Тед, где, как вы думаете, хранится поле BigInteger в объекте? –