Question

  

Double possible:
   Pourquoi les structures mutables sont-elles diaboliques?

Je l'ai lu dans beaucoup d'endroits, y compris ici qu'il est préférable de rendre les structures aussi immuables.

Quelle est la raison derrière cela? Je vois beaucoup de structures créées par Microsoft qui sont mutables, comme celles de xna. Il y en a probablement beaucoup plus dans la BCL.

Quels sont les avantages et les inconvénients de ne pas suivre cette directive?

Était-ce utile?

La solution

Les structures doivent représenter les valeurs . Les valeurs ne changent pas. Le nombre 12 est éternel.

Cependant, considérez:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

Now foo.Bar et foo2.Bar sont différents, ce qui est souvent inattendu. Surtout dans les scénarios comme propriétés (heureusement le compilateur détecte cela). Mais aussi des collections, etc. comment les mute-t-on de manière sensée?

La perte de données est beaucoup trop facile avec des structures mutables.

Autres conseils

Le gros inconvénient, c’est que les choses ne se comportent pas comme vous le souhaiteriez - en particulier si la mutabilité provient d’un mélange de la valeur directe et d’un type de référence.

Pour être honnête, je ne me souviens pas de tous les problèmes étranges que j’ai vus rencontrer dans les groupes de discussion quand ils ont utilisé des structures mutables - mais ces raisons existent certainement. Les structures mutable posent problème. Restez à l'écart.

EDIT: Je viens de trouver un email que j'ai écrit il y a quelque temps sur ce sujet. Il élabore juste un peu:

  • C'est philosophiquement faux: une structure doit représenter une sorte de valeur fondamentale. Celles-ci sont fondamentalement immuables. Vous ne pouvez pas modifier le nombre 5. Vous pouvez modifier la valeur d'une variable de 5 à 6, mais vous ne modifiez pas logiquement la valeur elle-même.

  • C'est pratiquement un problème: cela crée beaucoup de situations étranges. C'est particulièrement grave s'il est modifiable via une interface. Ensuite, vous pouvez commencer à changer les valeurs encadrées. Ick. J'ai vu beaucoup de messages de groupes de discussion qui sont dus à des personnes essayant d'utiliser des structures mutables et se heurtant à des problèmes. J'ai vu un très étrange exemple LINQ qui échouait parce que List<T>.Enumerator est une structure, par exemple.

J'utilise souvent des structures mutables dans mon projet (performances critiques) - et je ne rencontre pas de problèmes, car je comprends les implications de la sémantique de la copie. Autant que je sache, la raison principale invoquée par les personnes qui préconisent des structures immuables est que les personnes qui ne comprennent pas les implications ne puissent se mettre dans le pétrin.

Ce n’est pas si terrible, mais nous risquons à présent de devenir & "la vérité de l’Évangile &"; alors qu’il est légitimement la meilleure option struct mutable. Comme pour toutes choses, il existe des exceptions à la règle.

Il n’existe rien de moins coûteux à manipuler qu’une structure mutable. C’est pourquoi on la voit souvent dans un code de haute performance, comme les routines de traitement graphique.

Malheureusement, les structures modifiables ne fonctionnent pas bien avec les objets et les propriétés, il est beaucoup trop facile de modifier une copie d'une structure au lieu de la structure elle-même. Ainsi, ils ne sont pas appropriés pour la plupart de votre code.

P.S. Pour éviter les coûts de copie de structures mutables, elles sont généralement stockées et passées dans des tableaux.

La raison technique est que les structures mutables semblent être capables de faire des choses qu’elles ne font pas réellement. Étant donné que la sémantique de conception est la même que celle des types de référence, cela crée de la confusion pour les développeurs. Ce code:

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

Se comporte assez différemment selon que MySomething est un struct ou un class. Pour moi, c'est une raison impérieuse, mais pas la plus convaincante. Si vous consultez les DDD Objet de valeur , vous pouvez voir la connexion à la façon dont les structures doivent être traitées. Un objet de valeur dans DDD peut être représenté comme un type de valeur dans .Net (et par conséquent, une structure). Parce qu’il n’a pas d’identité, il ne peut pas changer.

Pensez à ceci en termes d’apparence similaire à votre adresse. Vous pouvez & Quot; changer & Quot; votre adresse, mais l'adresse elle-même n'a pas changé. En fait, vous avez une nouvelle adresse qui vous est assignée. Sur le plan conceptuel, cela fonctionne, car si vous changez votre adresse, vos colocataires devront également déménager.

Vous avez demandé le pour et le contre de ne pas suivre la directive selon laquelle les structures doivent être immuables.

Inconvénients: Les inconvénients sont bien couverts dans les réponses existantes et la plupart des problèmes décrits sont dus à la même cause - comportement inattendu en raison de la sémantique de la valeur de structs .

Avantages: Le principal avantage de l'utilisation de structures mutables peut être la performance . Évidemment, ce conseil contient toutes les mises en garde habituelles concernant les optimisations: assurez-vous qu'une partie de votre code nécessite d'être optimisé et assurez-vous que tout changement optimise réellement les performances de votre code via le profilage.

Pour un excellent article sur la possibilité d'utiliser des structures mutables, consultez la section Quiz sur les performances de la programmation basée sur la valeur (ou plus précisément, les réponses ).

Une structure doit généralement représenter une seule unité. En tant que tel, changer une des propriétés de la valeur n'a pas beaucoup de sens, il est plus judicieux de créer une toute nouvelle valeur si vous voulez une valeur différente.

La sémantique devient plus simple lorsque vous utilisez des structures immuables et vous évitez les pièges de ce type:

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

Le résultat est que la structure dans la liste n'est pas modifiée du tout. L'expression Interval [0] copie la valeur de la structure dans la liste, puis vous modifiez la propriété de la valeur temporaire, mais la valeur n'est jamais remise dans la liste.

Edition: modification de l'exemple pour utiliser une liste au lieu d'un tableau.

Lorsque vous copiez des structures autour de vous, copiez leur contenu, donc si vous modifiez une version copiée, le & "; original &"; ne sera pas mis à jour.

C’est une source d’erreurs car même si vous savez que vous tombez dans le piège de copier une structure (juste en la passant à une méthode) et de modifier la copie.

Il m'est arrivé de à nouveau la semaine dernière, m'a gardé une heure à la recherche d'un bogue.

Garder les structures immuables empêche que ...

Autre que cela, vous devez vous assurer que vous avez une très bonne raison d'utiliser des structures en premier lieu - & "; optimisation &"; ou " je veux quelque chose qui alloue rapidement sur la pile " ne compte pas comme une réponse. Marshaling ou des choses dont vous dépendez de la mise en page - ok, mais vous ne devriez généralement pas garder ces structures trop longtemps, ce sont des valeurs et non des objets.

la raison pour laquelle vous devez rendre les structures immuables est qu'elles sont ValueTypes , ce qui signifie qu'ils sont copiés chaque fois que vous les transmettez à une méthode.

Ainsi, si, par exemple, vous aviez une propriété qui renvoyait une structure, modifier la valeur d'un champ sur cette structure ne servirait à rien, car le getter renverrait une copie de la structure, plutôt qu'une référence à la structure. J'ai vu cela se faire dans le code, et c'est souvent difficile à attraper.

Si vous concevez vos structures pour leur immuabilité, vous aidez le programmeur à éviter ces erreurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top