For something to be passed by reference, the declared type of the parameter must precisely match the declared type of the thing being passed. Boxing only occurs when a value type is converted to something whose declared type isn't a value type, and thus isn't precisely the same as the value type in question.
Some people may dislike mutable value types, but passing mutable value types by reference is often superior to the evil practice of passing promiscuous references. For example, consider:
struct StructType1 {public int V; ... }
class ClassType1 {public int V; ... }
void blah()
{
StructType1 s1;
ClassType1 c1 = new ClassType1();
... do some stuff...
Routine1(s_pt, c_pt);
Routine2(ref s_pt, ref c_pt);
... do more stuff
}
What effect can Routine1 have on S1.V? What effect can routine1 have on C1.V?
What effect can Routine2 have on S1.V? When might such effects take place? How about with C1.V? In particular, is there any way of knowing whether Routine1 or Routine2 might cause C1.V to change at any arbitrary time in the future, long after the call has returned?
Also, suppose S1 holds some data I want to store into a class. If S1 contains nothing but value types (which may or may not be mutable) and immutable reference types, do I need to worry about anything unexpectedly altering the data I stored there?
Now suppose it was C1 that held the data I wanted to store. If C1 is mutable, or contains any mutable reference types, and I've exposed it to any outside functions, is there any way I can safely store the information contained therein without having to know a fair amount about the internals of C1?
Passing structs by reference is a beautiful way of allowing other functions to supply multiple pieces of information, without redundant copying. Supporting mutable value types may be a nuisance for language implementors, but value semantics are very useful in production code, despite some unfortunate quirks in some frameworks' implementations of them.