And even if you use structs with the goal of avoiding allocations, the language doesn't prevent you from accidentally writing code that upcasts them to `object` (eg by calling anything that the struct inherits from `object` and isn't overridden by the struct itself.) This transparently copies the struct to a heap allocation and negates your intent.
This is not entirely true as of C# 7.2. That version of the language adds "ref structs" - which can only be allocated on the stack and cannot be boxed [1].
This requires some care though, as the struct may still be copied needlessly if it is not also marked as `readonly` [2].