理解COM c#接口

时间:2014-07-11 08:15:19

标签: c# com com-interop

Microsoft.Office.Interop.Word._Document接口有一个带有以下签名的方法:

void Close(ref object SaveChanges = Type.Missing, ref object OriginalFormat = Type.Missing, ref object RouteDocument = Type.Missing);

我无法理解的几点:

  1. ref参数不能具有默认值。
  2. 默认值必须是常量,Type.Missing不是。
  3. 调用此方法时,我可以使用Close(false) - 通常一个ref参数需要一个可赋值的变量吗?
  4. 在Visual Studio中导航到Type的定义时,它会转到_Document.Type属性,但是它没有名为Missing的属性。这是VS中的错误吗?
  5. 感谢您的任何解释。

2 个答案:

答案 0 :(得分:4)

问题是,InterOp库实际上并不是用C#编写的,并且不必符合C#的规则。它唯一必须是有效的IL。

Visual Studio元数据查看器会尽力以您选择的语言(在本例中为C#)显示元数据,因为它通常比使用IL代码更具可读性。

在某些情况下这可能会产生误导(例如,在C#中实际上不必是ref的{​​{1}}参数,在C#具有默认参数之前的默认参数,默认情况下的非常量值参数...),但它实际上只是一个副作用,即VS并不真正知道用于构建库的语言,即使它确实如此,你也不希望看到 - 你关心在C#中暴露给你的界面,或者尽可能接近它的东西。

请注意,这些默认参数实际上与C#完全不同 - 在客户端编译时解析C#(例如,更改引用库中的默认参数不会在用户代码中更改它们,直到您重新编译该代码为止< / em>),这些都不是。正如我所说,VS尽力接近,但CLR语言确实非常不同。

答案 1 :(得分:3)

这是一个怪癖,在C#版本4中引入。它不是COM互操作代码所独有的,您也可以在自己的代码中获取它。试试这个:

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
    }
}

触发此行为的是[Optional]属性。永远存在,但在C#之前从未特别有用。与VB.NET和C ++ / CLI等其他语言不同。从C#v4开始,它以不同的方式解释属性,编译器将硬编码Type.Missing作为参数类型 object 的可选值。尝试将参数类型更改为,例如 string ,并注意默认值不同。没问题,正如你所期望的那样。

当然,这并不是非常漂亮,Type.Missing是普通C#代码中 object 的一个相当奇怪的默认值。每个人都希望 null 。然而,这非常实用,在4#之前的版本中用C#编写Office互操作代码是一个相当可怕的练习。当他们做这样的事情时,公司可能会遇到麻烦,如果Neelie Kroes得知它,她会让微软支付10亿欧元罚款:)