If you have been following my series on delegates, you may have experimented with open-instance delegates and perhaps found it difficult to create an open-instance delegate for a value type.
If you'll recall, an open-instance delegate has an extra first parameter, used to pass the instance used for the invocation. What's not made explicitly clear is that this first parameter must be passed by reference.
For reference types, you've automatically got a reference, but for value types, this must be a "ref" parameter. For instance, a delegate type used as an open-instance delegate for Int32.CompareTo would have to be defined something like:
delegate int IntCompareToDelegate(ref int instance, int other);
Otherwise, you'll get a System.ArgumentException when you try to bind the method to the delegate, giving you the ever-helpful error message: "Error binding to target method".
There are lots of underlying reasons for this, both from a calling convention perspective, as well as a side-effect perspective. But, you can simplify it by thinking about modifications to the instance. If you passed by value (creating a copy that the method acted on), any changes made to the instance by the method would be lost because they happened to a copy.
In most cases, value types are immutable in the framework, but you could run into issues with your own types. And, again, this isn't the only reason for this restriction (take a look at the IL generated for a value-type method call to get some more ideas). It's just the easiest to understand.
If you'll recall, Orcas extension methods, which are similar in concept to this, do not follow this pattern and are subject to the infamous value type copying problems.