我应该在 C++/CLI class 中使用 C# 对象的引用还是实例?
Should I use a reference or an instance of C# objects in a C++/CLI class?
在托管 C++ class 中,我应该使用在另一个库中实现的 C# class 的引用还是实例?
考虑这个例子:
// 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# 代码调用托管 class:
// 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
的一个实例呢?这样做的后果是什么?如果我的 class 只有一个 MyCSharpClass
对象集合,直接初始化集合是否有害?
C++/CLI 有一个名为 stack semantics 的功能,当您将引用类型成员声明为值类型 (MyCSharpClass myInst;
) 时,您正在使用它。
gcnew
仍在调用,但您看不到这段代码,因为编译器会自动将它注入您的默认构造函数。请注意,它还会生成代码来处理 myInst
!
下面是编译器将为您的 class:
生成的 MSIL 等效的(伪)C++/CLI 代码
构造函数:
MyManagedClass()
{
myInst = gcnew MyCSharpClass();
}
处置:
void Dispose(bool dispose)
{
if (dispose)
{
try
{
this->~MyManagedClass();
}
finally
{
delete myInst;
}
}
}
编辑:
关于你关于反响的问题:使用 gcnew
手动分配意味着当你的 MyManagedClass
对象死亡时,myRef
指向的对象将仍然存在,直到垃圾收集器清理起来;而通过使用堆栈语义,您可以更确定地控制对象生命周期,而无需自己编写 Dispose
方法。
这也意味着在使用堆栈语义时,您必须小心与谁共享对象...
在托管 C++ class 中,我应该使用在另一个库中实现的 C# class 的引用还是实例?
考虑这个例子:
// 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# 代码调用托管 class:
// 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
的一个实例呢?这样做的后果是什么?如果我的 class 只有一个 MyCSharpClass
对象集合,直接初始化集合是否有害?
C++/CLI 有一个名为 stack semantics 的功能,当您将引用类型成员声明为值类型 (MyCSharpClass myInst;
) 时,您正在使用它。
gcnew
仍在调用,但您看不到这段代码,因为编译器会自动将它注入您的默认构造函数。请注意,它还会生成代码来处理 myInst
!
下面是编译器将为您的 class:
生成的 MSIL 等效的(伪)C++/CLI 代码构造函数:
MyManagedClass()
{
myInst = gcnew MyCSharpClass();
}
处置:
void Dispose(bool dispose)
{
if (dispose)
{
try
{
this->~MyManagedClass();
}
finally
{
delete myInst;
}
}
}
编辑:
关于你关于反响的问题:使用 gcnew
手动分配意味着当你的 MyManagedClass
对象死亡时,myRef
指向的对象将仍然存在,直到垃圾收集器清理起来;而通过使用堆栈语义,您可以更确定地控制对象生命周期,而无需自己编写 Dispose
方法。
这也意味着在使用堆栈语义时,您必须小心与谁共享对象...