What happens when you change a struct to a class in .NET if you don’t recompile the type’s dependencies?
An interesting issue arose out of a recent code review I was conducting. If you change a type from a struct to a class, do you have to recompile all modules that are dependent on that type?
Let’s use a simple example. The following diagram illustrates several packages that are dependent on a “Geometry” package, with the Geometry package containing a struct called “Point”:
Point is defined as follows:
In the dependent module, I’ve defined a class called “Consumer” and created a constructor that references the Point struct:
Let’s examine this constructor in IL:
Pay attention to lines 5 through 7; the “valuetype” instruction declares an instance variable as a value type. This is important, because it means that the memory that the variable “point” occupies will be passed by value, not by reference. Also notice line 13; this call’s the Point struct’s constructor.
If the Point struct changes to a class, the IL in lines 5 through 7 will throw an exception, because classes can’t be declared as value types. If we change, the Point struct to a class and recompile the Geometry and dependent modules, the constructor’s init block looks like this:
Notice how the point variable is now being defined with the “class” instruction, telling the native-compiler to treat this variable as a reference type. Also, the call to initialize the variable has changed:
Instead of using the “initobj” instruction, the “newobj” instruction is being used.
The impact of this nuance is very small, because everybody is either using a continuous-integration server to build their solutions (I hope). However, when you’re attempting to perform local changes on your development box this problem can manifest itself.