System.Reflection.AssemblyName is a class. From a pragmatic point of view, the discussion ends here. Classes in .net are usually used to represent entities, not value types. Yet in this case, the concept behind an assembly name strongly suggests that it should be a value type. The name itself carries no identity, it only denotes an entity. Classes and Structures in C# are used using the same syntax, so if you don’t read the manual, it’s not obvious that AssemblyName is a class. This leads to interesting questions about how to handle equality. The developers of the .net framework chose not to override the Equals() method, so the default method comparing object identity is used. Therefore you can create two instances of AssemblyName with equal attributes for which Equals() returns false. While this is a technically valid choice, I consider it a violation of the principle of the least astonishment. Maybe it is because it took me quite some time today to debug an issue based on a broken usage of the Equals() method. And there a quite a few value types in the framework which work as expected, such as System.DateTime.
So how can you prevent making this mistake yourself? I consider chosing between class and struct to be one of the most important decisions when creating a new type. The Domain-Driven Design book by Eric Evans is a good start for this kind of decision.
Given that there is no rule how to always get it right, what can you do if your misrepresented value type is already in the field, used by dozens of developers? I don’t have a good answer for this one. Marking it obsolete and adding an improved type seems to be the only practical way, apart from ignoring the issue. But it has its draw-backs, such as the perfect name already being taken (how would you call an AssemblyName value type?) and many warnings starting to appear in perfectly working dependent code? I appreciate any comment on this.