作为 c++/cli 函数参数的通用结构在 VS 2015 中导致错误 CS0570,但在 VS2013 中没有

Generic Struct as argument to c++/cli function causes error CS0570 in VS 2015 but not in VS2013

我们有一个在 VS2013 中完美编译但在 VS2015 中编译错误失败的解决方案。

问题已缩小为:

我们有一个 c# 项目 A,它定义了一个通用结构,如下所示:

public struct MyStruct<T>
{

    public MyStruct(T b)
    {
    }
}

我们有一个 c++/cli 项目 B,它定义了这样一个函数:

public ref class Class1
{

public:
    void BadMethod(MyStruct<int> ^){};
};

最后我有一个 c# 命令行项目 C 引用项目 A 和 B 并尝试调用 BadMethod:

  class Program
    {
        static void Main(string[] args)
        {
            var c = new Class1();
            var s = new MyStruct<int>(0);

            c.BadMethod(s);
        }
    }

在 Visual Studio 2013(及更早版本)中编译没有任何问题,在 Visual Studio 2015 中我们得到:

application\Program.cs(18,15,18,24): error CS0570: 'Class1.BadMethod(?)' is not supported by the language

我尝试使用 Visual Studio 2015 工具集编译 c++/cli 项目,但错误仍然存​​在。

使用通用 class 而不是结构似乎可行。

   void BadMethod(MyStruct<int> ^){};

一个新的 VS 版本被指责为编程错误的频率相当惊人。 MyStruct 类型是 值类型。但是您将参数类型声明为引用类型变量。请注意您使用的 ^ 帽子。

有些遗憾,C++/CLI 编译器支持此功能。 CLR 也是如此,值必须先 boxed 才能传递给方法调用。非常低效,使用值类型的目的总是避免装箱。然而,对于这种盒装类型,CLR 中没有可用的类型注释,它在元数据中变为 System::ValueType。通过运行时检查该值是否属于预期类型。效率低下,加起来就是大笔钱。

C# 语言根本不支持这一点,并且吐出子弹必须将值装箱。没有任何方法来检查它是否是 required 值类型,它非常重视静态类型检查。

修复非常简单,只需省略 ^ 即可使参数按值传递,而不必装箱。如果您打算通过引用传递值,但问题不清楚,那么您必须改用 %

检查其余代码可能是个好主意,C++/CLI 使得在编译器没有任何窥视的情况下很容易搞砸并失去大量性能。应用简单的规则,值类型的变量必须 永远不会 有帽子。除非堆栈语义(C# 中的 using 语句)是预期的,否则引用类型的变量应始终具有帽子。