Even though that the statement in the title is trivial, the fact that the syntax of automatic properties and fields is almost identical can sometimes make us forget that they are two different things. Take, for example, the following struct:
Let’s assume that it is marshaled and passed to an unmanaged function:
The unmanaged function expects a pointer to a struct that contains 4 integers, where the first integer holds the data for A, the second integer holds the data for B, the third for C, and the forth for D. That is why the struct is decorated with the StructLayout attribute with Sequential LayoutKind, which guides the loader to preserve field order as declared.
What will happen if, for some reason, we implement the C field as an automatic property?
To answer the question, we need to remember that automatic properties are just a syntactic sugar and when encountered by the compiler, a backing field is automatically generated for them, along with the ordinary get and set methods. The automatically generated backing field will usually be emitted after all the regular fields, and therefore will not preserve the original declaration order.
This is the actual memory layout of the original struct:
And this is the memory layout of the struct with C implemented as an automatic property:
You can see that the compiler has automatically generated a field named <C>k__BackingField, and placed it after the D field, even though it was before it in the struct’s declaration. Given the above memory layout, the struct will not be marshaled as expected. Specifically, the C and D fields will change places, causing the unmanaged function to read invalid data. Solving the problem by changing the StructLayout to Explicit is not possible as it will cause the compiler to fail with the following error message: "Automatically implemented properties cannot be used inside a type marked with StructLayout(LayoutKind.Explicit)".
The scenario that I presented is fairly esoteric, but may cause some hard to find bugs. I strongly recommend not to use automatic properties in classes or structs that are used across boundaries.