在托管的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);
}
}
我的直觉告诉我,我应该使用myRef
和listRef
,因为如果这是在C#中实现的话,那就是我要做的。但为什么我可以直接实例化MyCSharpClass
的实例?这样做的后果是什么?如果我的班级只有一个MyCSharpClass
个对象的集合,那么直接初始化集合是否有害?
答案 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
方法。
这也意味着当使用堆栈语义时,你必须小心谁与...共享对象