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

时间:2015-04-28 22:43:39

标签: 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
    };
}

然后从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);
    }
}

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

1 个答案:

答案 0 :(得分:5)

C ++ / CLI有一个名为stack semantics的功能,当您将引用类型成员声明为值类型(MyCSharpClass myInst;)时,您正在使用该功能。

仍然会调用

gcnew,但是您没有看到此代码,因为编译器会将其自动注入默认构造函数中。请注意,它还会生成处理myInst的代码!

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

构造

MyManagedClass()
{
    myInst = gcnew MyCSharpClass();
}

<强>配置:

void Dispose(bool dispose)
{
    if (dispose)
    {
        try
        {
            this->~MyManagedClass();
        }
        finally
        {
            delete myInst;
        }
    }
}

编辑:

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

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