Imagine, .NET didn't have
DateTime struct, what would you do then? Sure, some of you would find a library (or write the library), but I bet most of the time, we would simply pass a date as a
string or an
int (e.g. epoch time). This is known as a primitive obsession.
4 Good Reasons for Primitive Obsession
C# structs are an amazing tool for managing complexity in your code. They allow hiding the details of the implementation behind a nice facade.
DateTime struct allows for formatting, parsing, calculations, without you needing to worry about anything. Yet, it seems we rarely create value types in our code; instead, we follow this primitive obsession in a lot of places. I can see at least 3 problems here.
Don't know any better
Firstly, I don't think many developers realize they have this tool at their disposal. I have conducted interviews and graded coding exercises, and in my personal experience, it is extremely rare for candidates to model values using structs (but most of them will tell you they are allocated on a stack and not the heap ;)).
It is not clear cut - is it a value or a primitive?
Of the handful of developers that realize they can use structs, many of them, and I include myself in this category, sometimes struggle to draw a line of creating structs that are actually useful. For example, I work in a finance company, should
Money be a value or should I use a
decimal? Decimal has got all the methods I need (namely addition, subtraction, multiplication, and division).
Am I just creating more work?
Building on that, and perhaps even more importantly,
decimal is supported by a host of libraries that can work with them -
System.Math is a good example. You can try taking a step further, by for example using implicit and explicit casing, adding operators, and implementing assorted interfaces (
IEquatable as a start). The code below has 165 lines of code. Plus, whatever unit tests you want to add, so is it worth the effort?
What if it has to be public
Finally, whenever you create a custom value type, you need to think through the implications of serializing values, be that for storage or communication. Many frameworks nowadays offer some sort of value converters e.g. MongoDB, EF Core, JSON. But this is yet more code, you have to write and test.