【问题标题】:COM Interop Method Signature with ByRef带有 ByRef 的 COM 互操作方法签名
【发布时间】:2026-02-02 08:30:01
【问题描述】:

我有一个 C# 程序,它调用一个 COM DLL,它有一个名为 test 的方法,带有两个参数:第一个参数传递给 ByVal,第二个参数传递给 ByRef

这就是 COM DLL 的作用:

Public Sub test(ByVal a As String, ByRef b As String)
    a = "a"
    b = "b"
End Sub

这就是 C# 程序的作用:

test.Class1 x = new test.Class1();
            string a = "1";
            string b = "2";
            x.test(a, ref b);

我注意到,如果我删除 ref 关键字,编译器不会告诉我我错过了 ref 关键字并传递参数 ByVal。如果我错过了ref 关键字,这可能是一个大问题,因为在我知道它需要ref 之前我不会注意到它。你知道为什么编译器会出现这种行为吗?

【问题讨论】:

  • @MartinVerjans C# 项目中没有“Option Strict ON”
  • @HansPassant 我测试了没有 ref 关键字的程序,它不会改变字符串的值。因此,如果您不告诉他这样做,请传递字符串 ByVal 而不是 ByRef。

标签: c# vb6 com-interop byref byval


【解决方案1】:

这高度特定于 COM 互操作代码和 C# 语言版本 4 及更高版本。是的,它允许在这种特定情况下省略 ref。 C# 版本 4 进行了很多调整,使 Office 编程更容易。 Office api 最初旨在与早期的 VB 版本很好地配合使用,默认情况下它们使用 ByRef。 VBA 仍然如此。所以 api 有 lot 的方法参数是 ByRef,即使它们实际上并没有修改传递的参数。

如有必要,编译器将生成一个临时变量以使调用合法。结果是您的变量没有得到更新。你需要注意的事情。前进两步,后退一步:)

【讨论】:

  • 如果我有一个大项目,我想检查每一个错过的“ref”关键字,我该怎么做?或者有什么可以告诉我这个错误?
  • Hmya,您必须使用明显的方法来查找代码中的错误,您使用调试器。不要惊慌,仅仅因为你错了一个并不意味着你都错了。 IntelliSense 仍然可以帮助您做对。请先修复那个 COM 代码,它当然应该是一个函数。
  • 也许你不明白我的问题。问题是这样的:如果我错过了 COM 方法签名中的 ref 关键字,编译器会接受它,即使该方法实际上需要一个 ByRef 参数,也不会告诉我任何信息。在一个大项目中,我不能检查每一个方法,它们是签名(我可以,但需要很多时间)。如果我错过了 ref 关键字,我只希望编译器建议我。
  • 很确定我理解你的问题。也许你不明白“退一步”是什么意思。这意味着在第 4 版中添加了一个 潜在问题。调试从来都不是一个困难的问题,它的值没有改变是非常明显的。不要惊慌。
  • 叹息,你不会放松的吧?好吧,写一个 Roslyn 代码分析器,你可以比较调用和方法声明,看看不匹配。谷歌“编写 roslyn 代码分析器”以获得成功。
最近更新 更多