9
votes

BigInteger est-il immuable ou pas?

in .NET 4 BETA 2, il y a le nouvel espace de noms numériques avec struct biginteger . Documentation stipule que C'est un type immuable, comme je l'aurais attendu.

Mais je suis un peu confus par l'opérateur post-incraction ( ++ ). Cela semble non-muté de la valeur. Les travaux suivants tandis que la boucle fonctionne: xxx

C'est ce que MSDN dit à propos de l'opérateur d'incrément:

Parce que les objets BigInteger sont immuable, l'opérateur d'incrément crée un nouvel objet BigInteger dont la valeur est une plus que la biginteger objet représenté par la valeur. Par conséquent, des appels répétés à l'incrément peut être cher.

Bien et bien, j'aurais compris si je devais utiliser b = b ++ mais apparemment ++ est suffisant pour changer une valeur .

Toutes les pensées?


0 commentaires

5 Réponses :


14
votes

Les opérateurs ++ et - sont implémentés en termes de normal + et - opérateurs, donc en réalité: xxx

est équivalent à: xxx

maintenant, comme commenté, cela peut sembler comme ça casse une immuabilité, mais elle fait pas.

Vous devez plutôt regarder ce code comme le faisant: xxx

Ceci laissera deux objets en mémoire, la valeur de BigInteger d'origine et la Nouveau, maintenant référencé par b. Vous pouvez facilement vérifier que c'est ce qui se passe avec le code suivant: xxx

de sorte que l'objet d'origine n'a pas changé, il ne casse donc pas l'immuabilité et de répondre à la nouvelle partie. de la question, cela devrait être du thread-coffre-fort.

C'est la même chose qui arrive à des chaînes: xxx


2 commentaires

Cela semble raisonnable, mais il semble toujours casser l'immuabilité. Je vais éditer la question un peu.


Dans S + = S2 Il existe une affectation visible. Il convient si vous acceptez que B ++ est également une affectation, c'est-à-dire b = b + 1 . Mais ++ reste toujours / ressemble à la mutation.



3
votes

Étant donné que BigInteger est immuable, B ++ sera juste équivalent à: xxx

Après cette opération, la température est recyclée par le GC et la mémoire est libérée.


4 commentaires

OK, sauf pour la partie GC. C'est une structure (avec un tableau interne).


Oui, et la seule différence est que la structure est stockée sur la pile alors que cette classe est stockée dans le tas.


Ted, où pensez-vous qu'un champ de biginteger dans un objet est stocké?


C'est dans le tas, avec une référence à elle stockée sur la pile.



-1
votes

OK, mais qu'en est-il de l'opérateur de négation unaire défini sur BigInteger: xxx

Il semble casser le motif d'immutabilité et muter directement l'objet BigInteger. Donc xxx

modifie réellement une biginteger existante en place sans retourner un nouvel objet.


0 commentaires

0
votes
BigInteger b = BigInteger.One;

b++;  // immutable ?
In your example b is a variable, which is just a slot of memory in the current method's stack frame. It is initialised to One, and b++ takes b, creates a new BigInteger (with the incremented value) and returns it. variable b now has the state from the returned new BigInteger.To be honest immutability as a concept is much clearer when dealing with reference types, because there is an object on the heap whose internal state never changes, so when an operation/method returns a new object with different state it's kind of obvious (e.g. you can do an object reference equality check with object.ReferenceEquals(object, object).For value types there is no object on the heap, there is just the slot in memory that contains the bits that are the value.

0 commentaires

-1
votes

de la Microsoft Docs, juste après avoir parlé de ++:
Bien que cet exemple semble modifier la valeur de l'objet existant, ce n'est pas le cas.
Les objets BigInteger sont immuables, ce qui signifie qu'intier, le jeu de langue commune crée en fait un nouvel objet BigInteger et l'attribue une valeur supérieure à celle de sa valeur précédente. Ce nouvel objet est ensuite retourné à l'appelant.


8 commentaires

Non, BigInteger est une structure (type de valeur) et il n'y a pas de pointeur (référence) ici.


@HENKHOLTERMAN Eh bien, le pointeur est soit en B, soit dans une structure que B pointe de chaque sens, un peu de pointe doit changer.


@HENKHOLTERMAN OK, je vais vous donner un exemple, disons que vous avez une chaîne, qui est un type de valeur et que vous le transmettez à une fonction, si vous regardez dans le désastage, vous verrez qu'une seule valeur de 64/32 bits est transmis comme un paramètre à la fonction, car notre chaîne a probablement plus de 64 bits, nous pouvons supposer que nous ne passions pas la chaîne, nous passons un pointeur, un pointeur sur une copie de la chaîne, mais toujours, un aiguille.


Une chaîne est un type de référence. BigInteger n'est pas. Il existe de meilleures références que le code IL.


@Henkholeshterman mon mauvais, mais j'en ai un meilleur exemple, si vous passez une grande structure à une fonction, vous passez un pointeur sur la structure même si une structure est un type de valeur.


Êtes-vous confondre cela avec C ou C ++?


Il semble que je suis, je modifierai ma réponse pour être correct, désolé


Et maintenant comparez-le à la meilleure réponse ici.