【问题标题】:C#6/C++ ref keyword errorC#6/C++ ref 关键字错误
【发布时间】:2014-11-18 09:18:14
【问题描述】:

我用我现有的解决方案尝试了 VS2015,我得到了一些有效的新错误(比如编译器之前没有捕获的无法访问的代码),但我也得到了一个错误,例如在这一行:

bool bWasAlreadyLocked = false;
oEnv.LockDoc(oWarnings, oEventDoc, ref bWasAlreadyLocked);

我收到以下错误:

错误 CS1503 参数 3:无法从 'ref bool [mscorlib, 版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089]' 'ref bool [mscorlib,版本=4.0.0.0,文化=中性, PublicKeyToken=b77a5c561934e089]'

我看不出它为什么会抛出那个错误,显然类型确实匹配。这是新编译器中的错误还是 ref 关键字的行为发生了变化?

本例中的函数是一个 C++ 函数,它使用从 c++ 类派生的 c# 类导入到 C#。它的签名是这样的:

void CBkgDocEnvX::LockDoc(
CFIWarningList ^oWarnings,
CBaseDoc ^oBaseDoc,
// Output
bool %rbWasAlreadyLocked)

值得一提的是,我现在选择对解决方案中的 c++ 源代码使用 VS2013 c++ 编译器,因此 c++ 端应该与以前相同。我的猜测是 c# 和 c++ 之间的互操作发生了一些变化。

【问题讨论】:

  • LockDoc的签名是什么?
  • 查了一下,是一个C++函数
  • % 似乎是一个c++ 跟踪运算符。不知道如何在 C# 中处理它。
  • 嗯,这是一个错误。您确实需要考虑错误消息也可能被窃听。 C++ bool 与托管 bool 不同,您可能通过将其声明为 System::Boolean 来获得成功。尽管尚不清楚您使用的是 C++/CX 还是 C++/CLI。使用 connect.microsoft.com 报告测试版错误。
  • 不幸的是,我到处都有这个问题,即使是我自己的类型。发送报告。

标签: c# c++ interop roslyn ref


【解决方案1】:

您应该检查这一点以确定。

  1. 只能通过引用传递 L 值。 L 值是可能出现在赋值左侧的变量和其他表达式。其中包括局部变量、字段访问、指针取消引用和数组元素访问。 L 值不包括属性访问,它们没有可识别的机器地址,也不包括受 CLR 限制的只读字段。
  2. 引用参数不能是扩展方法的目标。扩展方法调用对于值类型来说是昂贵的,因为“this”参数是按值复制的。这也意味着值类型不能有可变的扩展方法。这与通过引用传递值类型“this”参数的实例方法形成鲜明对比。
  3. 不能在运算符重载函数中使用引用参数。

您可以找到更多信息here

【讨论】:

  • 这听起来很合理,但并不新鲜。由于代码在 VS2013 中有效,我怀疑它是由其中一种情况引起的,但如果我错了,请纠正我。另外,你可以看到上面的 ref 参数声明。
【解决方案2】:

当两个项目的类型不兼容时,我会遇到这些类型的编译器错误。很多时候,即使引用项目的 .NET 配置文件类型不支持被引用的程序集,Visual Studio 也会允许我添加对可移植类库项目(或 .NET 4.0 项目)的引用。

对我来说,最常见的情况是在使用 .NET 4.0 项目并尝试引用在其配置文件设置中指定 .NET 4.5 而不是较旧的 .NET 4 版本的可能类库项目时。当我从我的 .NET 4.0 项目中引用 PCL 程序集时,我继续获得完整的智能感知支持(例如,在编辑源代码时智能感知将显示包含在被引用的程序集中的所有命名空间、类和属性)但在编译时我得到了您遇到的相同类型的错误;更具体地说,当我编译解决方案时,编译指示库不匹配,但列出了它说它正在寻找的完全相同的库、版本和公钥。

检查项目属性,验证它们是否兼容。

【讨论】:

    【解决方案3】:

    事实证明,这个错误可以通过显式添加一个out属性到参数中来修复。

    [Out] 添加到ref 参数显然有助于新的C# 编译器识别这些是相同的类型并接受它们。我们的互操作解决方案中的方法现在如下所示:

    using namespace System::Runtime::InteropServices;
    
    ...
    
    virtual void LockDoc(
       CFIWarningList ^oWarnings,
       CBaseDoc ^oBaseDoc,
    // Output
       [Out] bool %rbWasAlreadyLocked
       ) override;
    

    【讨论】:

      【解决方案4】:

      您可以尝试使用 Object 数据类型而不是 Boolean。之后,您可以将其解析为布尔值。

      【讨论】:

      • 或者我无法使用 VS2015,而这不起作用,而不是在整个项目的数百个地方删除打字;)
      猜你喜欢
      • 2010-10-28
      • 2010-12-31
      • 1970-01-01
      • 2011-06-16
      • 2011-11-24
      • 2010-12-02
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多