Turns out there's another way that VB tends to make Office development nicer. And that's because office uses late binding in a few places (dialogs were mentioned as one of those places). So in VB you could type something like:

Dim dialog as OfficeDialog
dialog = GetDialogSomehow()
dialog.Font = "wingdings"

Whereas in C# that would become:

OfficeDialog dialog;
dialog = GetDialogSomehow();
typeof(OfficeDialog).InvokeMethod("Font", BindingFlags.Public | BindingFlags.Instance, null, new object[] { "wingdings" }, null);

Yech. One interesting thing to realize is that by forcing explicit late binding in C# we force it to your attention that this might fail. At least, we try to make it pretty clear since reflection can end up throwing a whole host of exceptions. In the VB model that call seems completely innocuous and you wouldn't think to wrap that in a try/catch block.

Anson and I talked afterwards with the presenter. I asked: Wouldn't it make more sense to have something like this:

IDialogWithFonProperty d;
if ((d = dialog as IDialogWithFontProperty) != null)
      d.Font = "wingdings"

I.e. have nice safe interfaces/subclasses that one can cast to and get compile time checking on.

Anson's reponse was more general. He asked: Wouldn't it make sense for Office to provide a nice managed interface (a primary interop assembly) that fit well in with the .Net languages and abstracted a lot of these old design patterns away from the user.

The speaker thought that both ideas seemed good and that it was something they would look into trying to do.