在使用 "hat" 运算符和不使用 "hat" 运算符的情况下接受 C++/CLI 中的托管结构。有什么区别?

Accepting managed struct in C++/CLI both with "hat" operator and without. What is the difference?

我已经成功使用了很长时间的 C++/CLI 层。但我刚刚发现了一些让我觉得我需要重新学习一些东西的东西。

当我的 C++/CLI 函数接收到任何托管 class 的实例时,它们使用 "hat" 运算符('^')并且当它们收到托管 struct 的实例,但他们没有。我以为我应该这样写。

尽可能平淡地说明

using Point = System::Windows::Point;
public ref class CppCliClass
{
    String^ ReturnText(String^ text) { return text; }  // Hat operator for class
    Point   ReturnStruct(Point pt) { return pt; }      // No hat operator for struct
};

我认为这是必需的。它当然有效。但是就在今天我发现CancellationToken是一个struct,而不是class。我的代码接受了它。我写的时候还以为是一个class呢。这段代码工作得很好。我的取消在 C++/CLI 层中得到尊重。

void DoSomethingWithCancellation(CancellationToken^ token)
{
    // Code that uses the token.  It works just fine
}

显然我可以选择任何一种方法。

但是按值传递结构(就像我对我使用的所有其他结构类型所做的那样,比如 Point)和按引用传递(就像我对 CancellationToken 所做的那样?)有什么区别?有区别吗?

^ 对于引用类型,对于值类型不匹配 C#,但 C++/CLI 确实给了你更多的灵活性:

  • 没有 ^ 的引用类型被称为 "stack semantics" 并自动尝试在变量生命周期结束时对对象调用 IDisposable::Dispose。它就像一个 C# using 块,只是对用户更友好。特别是:

    • 无论类型是否实现IDisposable,都可以使用语法。在 C# 中,如果可以在编译时证明类型,则只能编写 using 块来实现 IDisposable。 C++/CLI 范围内的资源管理在泛型和多态情况下工作良好,其中一些对象实现而另一些不实现 IDisposable.

    • 语法可用于class成员,并自动在包含class上实现IDisposable。 C# using 块仅适用于本地范围。

  • ^ 一起使用的值类型被装箱,但静态跟踪确切的类型。如果传入不同类型的装箱值,您将收到错误消息。