Il n'y a rien de mal avec les structs qui ont des champs exposés, ou qui permettent la mutation via les setters de propriété. Les structs qui se mutent eux-mêmes en réponse aux méthodes ou aux accesseurs de propriété, en revanche, sont dangereux car le système permettra que des méthodes ou accesseurs de propriété soient appelés sur des instances de struct temporaires; si les méthodes ou accesseurs apportent des modifications à la struct, ces modifications finiront par être ignorées.
Malheureusement, comme vous le notez, les collections intégrées dans .net sont vraiment faibles pour exposer les objets de type valeur qu'elles contiennent. Votre meilleur choix est généralement de faire quelque chose comme :
MyStruct temp = myList\[1\];
temp.Name = "Albert";
myList\[1\] = temp;
Un peu ennuyeux, et pas du tout sûr avec plusieurs threads. Tout de même une amélioration par rapport à une Liste d'un type de classe, où faire la même chose pourrait nécessiter :
myList\[1\].Name = "Albert";
mais cela pourrait aussi nécessiter :
myList\[1\] = myList\[1\].Withname("Albert");
ou peut-être
myClass temp = (myClass)myList\[1\].Clone();
temp.Name = "Albert";
myList\[1\] = temp;
ou peut-être une autre variante. On ne pourrait vraiment pas le savoir à moins d'examiner myClass ainsi que les autres codes qui mettent des choses dans la liste. Il est tout à fait possible que l'on ne puisse pas savoir si la première forme est sûre sans examiner le code dans les assemblages auxquels on n'a pas accès. En revanche, si 'Name' est un champ exposé de MyStruct, la méthode que j'ai donnée pour le mettre à jour fonctionnera, peu importe ce que MyStruct contient d'autre, ou peu importe ce que d'autres éléments ont pu faire avec myList avant que le code ne s'exécute ou ce à quoi ils peuvent s'attendre à faire avec après.