Since it got downvote, I'm trying to rewrite a bit to see if it can become clearer. This question is old; but good! Recently, I also came across several links that describe this in detail.
What I'm trying to add is that if you declare reference fields, you should be able to reason outside your own block: when someone uses your structure. The specific point I added was really only about declaring a readonly field in a structure; but in this case, the fields that you have in your structure can change their results; and it's hard to reason.
I stumbled upon this link where the programmer declared a class containing the readonly struct field. The field in his class is struct --- it a LinkedList<T>.Enumerator - and it broke because the readonly field --- its own class methods get a copy of the enumeration structure, and the state is copied and not dynamic.
But , if you fix its code by simply removing readonly from the struct field (which works); and then, however, if you then decide to make your own class a struct , now again, the consumer of your structure will not be able to use it as a reading field, otherwise they, in turn, will be bitten by the same problem. (And if that seems tricky because you don't have an enumerator, only really if it supports Reset!)
So, if this is not the clearest example, what I am doing is that you can talk about your own implementation, but if you are a structure, you also need to know about the consumers who copy your value and what they will get.
Below is an example that I found.
Its class is not a struct , but contains the m_Enumerator field (and the programmer presumably knows that it is a struct ).
It turns out that the methods of this class receive a copy of this value and do not work. --- You can really study this unit very carefully to understand this.
You can fix this by not making the field readonly ---, which already indicates confusion. But you can also fix this by declaring the field as an interface --- IEnumerator<int> .
But if you fix this by leaving the field declared as struct and declaring it not readonly , and then select your class definition as struct , then now, if someone declares an instance of your struct as readonly field in some class, they are lost again !
eg:.
public class Program { private struct EnumeratorWrapper : IEnumerator<int> {
If you declare a struct with an interface field, you wonโt know what you have there, but still you can really learn more about what you get when you simply reference it! It is very interesting; but only because the language allows so many freedoms with struct : you need to start with something very simple; and add only what you can specifically substantiate!
Another point is that the link also states that you should define the default values โโas reasonable; what is impossible in the control field! If you inadvertently call the default constructor --- always possible with struct --- then you will get a null reference.
Also a final note. Many people advocate volatile structures and large volatile structures. But if you look inside, you usually find that they simply look at these objects in such a way that they can finally talk about behavior, and the structures do not leak in the area where these invariants could change.
... Too many people begin to explain structures as "Like a class, but ... x, y, z, 1, 2, alpha, beta disco." It needs to be explained as a pair of readonly values; period; besides the fact that you know something, you can start to talk about adding something!
The example I got accros is here:
https://www.red-gate.com/simple-talk/blogs/why-enumerator-structs-are-a-really-bad-idea/