The common language runtime supports three kinds of parameter passing.
By-value parameters work as one would expect. Primitive types are simply copied onto the stack, as are value types, object references, managed pointers, and unmanaged pointers.
CIL Type: typename
By-ref parameters of course references to other values. Any of the types that can be passed by value can also be passed by reference. However there certain restrictions. In order to get a reference to a value, that value must have a home. A home can be any of the following:
- An incoming argument
- local variable of a method
- An instance field of an object or value type
- A static field of a class, interface, or module
- An array element
At first glance the list appears to be comprehensive, but something is missing. Intermediate values, those which are on the stack but are neither a local nor a argument, do not have a home and thus cannot be referenced.
CIL Type: typename&
A typed reference parameter is a reference to a home matched with the argument’s type information. Normally it isn’t necessary to explicitly pass the argument’s type information as one of the following is usually true:
- The argument is a value type that matches the parameter type
- The argument is a reference type and thus the type information is encapsulated.
- The argument is a boxed value type, again with the type information encapsulated.
It is only when the argument is an unboxed value type that doesn’t necessarily match the parameter type that a Typed Reference is needed. This will never occur in a early-bound language such as the original version of C#, but it can in late-bound language such as VB with option strict turned off.
does and not
one that combines a by-ref parameter with extra type information. The reason this is necessary is that it is possible for an argument to otherwise lose it’s type. This occurs when…
- The parameter is a value-type. Value-types do not internally store their type unless boxed.
- The parameter is passed without boxing.
- The argument’s type doesn’t necessarily match
CIL Type: typedref
CLR Type: System.TypedReference