Foi útil?

Solução

Os operadores ++ e -- são implementadas em termos dos operadores + e - normais, assim, na realidade:

b++;

é equivalente a:

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

Agora, como comentado, isso pode parecer quebra imutabilidade, mas isso não acontece.

Você deve em vez olhar para este código como fazer isso:

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

Isso vai deixar dois objetos na memória, o valor original BigInteger, e o novo, agora referenciados por b. Você pode facilmente verificar que este é o que acontece com o seguinte código:

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

Assim, o objeto original não se alterou, portanto, ele não quebrar imutabilidade, e para atender a nova parte da pergunta, esta deve ser thread-safe.

Esta é a mesma coisa que acontece com strings:

String s1 = s2;
s2 += "More";
// now inspect s1 and s2, they will differ

Outras dicas

Desde BigInteger é imutável, b ++ será apenas o equivalente a:

BigInteger temp=b;
b=temp+1;

Após esta operação, a temperatura é reciclado pela GC e a memória é liberada.

BigInteger b = BigInteger.One;

b++;  // immutable ?

No seu exemplo b é uma variável, que é apenas um slot de memória do quadro de pilha do método atual. Ele é inicializado para um, e b ++ leva b, cria um novo BigInteger (com o valor incrementado) e devolve-lo. variável b agora tem estado a partir do novo BigInteger retornado.

Para ser imutabilidade honesto como um conceito é muito mais clara quando se lida com tipos de referência, porque não é um objeto na pilha cujo estado interno nunca muda, por isso, quando uma operação / método retorna um novo objeto com estado diferente é meio óbvio (por exemplo, você pode fazer uma verificação de igualdade de referência objeto com Object.ReferenceEquals (Object, Object).

Para tipos de valores não há nenhum objeto na pilha, não é apenas o slot de memória que contém os bits que são o valor.

Ok, mas o que acontece com o operador de negação unário que é definido em BigInteger:

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

aparece para quebrar o padrão imutabilidade e directamente transformar o objeto BigInteger. Então

b = -b;

realmente muda um BigInteger existente no local sem retornar um novo objeto.

scroll top