我应该在C++/CLI类中使用C#对象的引用还是实例?

djs*_*djs 2 c++-cli

在托管的c ++类中,我应该使用我在另一个库中实现的C#类的引用还是实例?

考虑这个例子:

// MyManagedClass.h
#pragma once

using namespace System::Collections::Generic;
using namespace My::Namespace::MyCSharpLib;

namespace My::Namespace::MyManagedLib
{
    public ref class MyManagedClass
    {
    public:
        MyCSharpClass myInst; // i have an instance!
        MyCSharpClass ^myRef; // need to do gcnew

        List<MyCSharpClass ^> listInst; // i have an instance!
        List<MyCSharpClass ^> ^listRef; // need to do gcnew
    };
}
Run Code Online (Sandbox Code Playgroud)

然后从C#代码调用托管类:

// driver.cs
using My.Namespace.MyCSharpLib;
using My.Namespace.MyManagedLib;

public class Driver
{
    private static void Main(string[] args)
    {
        MyManagedClass mmc = new MyManagedClass();
        DoStuff(mmc);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的直觉告诉我,我应该使用myRef,listRef因为如果这是在C#中实现的话,那就是我要做的事情.但为什么我可以直接实例化一个实例MyCSharpClass呢?这样做的后果是什么?如果我的班级只有一个MyCSharpClass对象集合,那么直接初始化集合是否有害?

eas*_*ter 5

C++/CLI有一个称为堆栈语义的功能,当您将引用类型成员声明为值类型(MyCSharpClass myInst;)时,您正在使用该功能.

gcnew仍然被调用,但你没有看到这段代码,因为编译器会自动将它注入你的默认构造函数.请注意,它还会生成要处理的代码myInst!

下面是编译器将为您的类发出的MSIL的(伪)C++/CLI代码:

构造函数:

MyManagedClass()
{
    myInst = gcnew MyCSharpClass();
}
Run Code Online (Sandbox Code Playgroud)

配置:

void Dispose(bool dispose)
{
    if (dispose)
    {
        try
        {
            this->~MyManagedClass();
        }
        finally
        {
            delete myInst;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

关于你关于反响的问题:手动分配gcnew意味着当你的MyManagedClass对象死亡时,指向的对象myRef仍然会挂起,直到垃圾收集器清理它为止; 而通过使用堆栈语义,您可以使用更加确定的方法来控制对象的生命周期,而无需自己编写Dispose方法.

这也意味着当使用堆栈语义时,你必须小心你与谁共享对象...

  • "生成解除myInst的代码"不,它不会.解除分配仍然由垃圾收集器管理.如果对象实现了`IDisposable`,它将自动调用`Dispose`.C++/CLI堆栈语义是C#`using`块的一个(更强大的)版本. (2认同)
  • 好多了.虽然您的EDIT段落仍然错误地暗示垃圾收集器在使用堆栈语义时不控制对象的生命周期.在堆栈语义对象超出范围之后,它已被处理(因此大部分无用),但它实际上并未死亡.在.NET规则下,您至少仍然可以在其上调用"Dispose",并且某些对象可能允许在处理后执行其他操作.正如你所说的那样,通过"共享"对象所做的引用并不是狂野的或悬空的指针,尽管使用它们可能会给你一个"ObjectDisposedException". (2认同)