In versions 1.0 and 1.1 of the .NET Framework, there was no way to pass a Variant of type VT_VARIANT | VT_BYREF to native code through PInvoke or COM Interop. The Interop layer would extract the actual type being passed to native and use the matching Variant type to create the marshaled Variant e.g. a string would always be passed as a VT_BSTR, an Int32 would always be passed as a VT_I4 and so on. During implementation of version 2.0, we (the CLR Interop team) received quite a few customer requests asking us to add this support.
One use of passing VT_VARIANT | VT_BYREF Variants is that the actual type of the Variant can be changed by the callee e.g. a Variant of type (VT_VARIANT | VT_BYREF)=>VT_DATE passed in such a manner can be changed to any valid Variant type on the native side i.e. (VT_VARIANT | VT_BYREF)=>VT_*. Supporting this scenario is especially important for MFC COM objects since the MFC IDispatch implementation explicitly checks for (VT_VARIANT | VT_BYREF) flags on every parameter declared as a VARIANT*.
So in version 2.0 and SP1 of version 1.1 the Interop team added a VariantWrapper class (to the System.Runtime.InteropServices namespace) to provide support for this scenario. Below are code snippets for the various usage scenarios---(1) latebinding to COM through reflection in C#, (2) implicit latebinding to COM in VB.NET and (3) calling a disponly COM interface in C# (the actual call made by the runtime is an IDispatch call):
(1) Late binding in C#