Q:

Understand COM c# interfaces

The Microsoft.Office.Interop.Word._Document interface has a method with the following signature:
void Close(ref object SaveChanges = Type.Missing, ref object OriginalFormat = Type.Missing, ref object RouteDocument = Type.Missing);

A few points I am having trouble understanding:

A ref parameter cannot have a default value.
A default value has to be a constant, and Type.Missing is not.
When calling this method, I can use Close(false) - normally a ref parameter requires an assignable variable?
When navigating to the definition of Type in Visual Studio, it takes me to the _Document.Type property, but this does not have a property named Missing. Is this a bug in VS?

Thank you for any explanations.

A:

The thing is, the InterOp library isn't actually written in C#, and doesn't have to conform to C#'s rules. The only thing it has to be is valid IL.
The Visual Studio metadata viewer tries its best at showing you the metadata in the language of your choosing (in this case, C#), because it's usually a lot more readable than using the IL code.
This can be misleading in some cases (e.g. the ref parameters that don't actually have to be refs in C#, default parameters before C# had default parameters, non-constant values in default parameters...), but it really is just a side effect of the fact that VS doesn't really know the language that was used to build the library, and even if it did, you wouldn't want to see that - you care about the interface exposed to you in C#, or something as close to it as possible.
Note that those default parameters actually work completely differently from C#'s - C#'s are resolved at compile time on client-side (e.g. changing default parameters in referenced libraries will not change them in user code until you recompile that code too), these are not. As I said, VS does its best to approximate, but the CLR languages can be very different indeed.

A:

It is a quirk, introduced in C# version 4.  It is not exclusive to COM interop code, you can also get it in your own code.  Try this:
using System;
using System.Runtime.InteropServices;

class Program {
    static void Example([Optional] object arg) { }
    static void Main(string[] args) {
        Example(   // <== Look at the IntelliSense popup here
    }
}

It is the [Optional] attribute that triggers this behavior.  Been around forever but was never particularly useful in C# before.  Unlike other languages like VB.NET and C++/CLI.  Starting with C# v4, it interprets the attribute differently and the compiler will hard-code Type.Missing as the optional value for an argument type of object.  Try changing the argument type to, say, string and note that the default becomes different.  Null, as you'd expect.
This isn't very pretty of course, Type.Missing is a rather odd default value for object in normal C# code.  Everybody would expect null instead.  It is however very practical, writing Office interop code in C# in versions previous to 4 was a rather dreadful exercise.  Companies can get into trouble when they do stuff like this btw, if Neelie Kroes gets wind of it she'd get Microsoft to pay a billion Euro fine for that :)

