虽然一个简单的解决方法是使用safe_cast<T>(x)
和 catch System::InvalidCastException^
,但当类型不匹配时,这会产生明显的异常处理开销(展开堆栈和所有相关的乐趣)。
我试图想出一种不同的方法。虽然我不会完全称它为simple,但它在不使用异常的情况下完成了它的工作。
#using <System.Core.dll>
namespace detail
{
generic <typename T> ref class is_instance_of_managed_helper sealed abstract
{
public:
static initonly System::Func<System::Object^, bool>^ is_instance_of = build();
private:
static System::Func<System::Object^, bool>^ build()
{
using System::Linq::Expressions::Expression;
auto param = Expression::Parameter(System::Object::typeid);
return Expression::Lambda<System::Func<System::Object^, bool>^>(
Expression::TypeIs(param, T::typeid),
param)->Compile();
}
};
template <typename T> struct is_instance_of_helper
{
static bool is_instance_of(System::Object^ obj)
{
return is_instance_of_managed_helper<T>::is_instance_of(obj);
}
};
template <typename T> struct is_instance_of_helper<T^>
{
static bool is_instance_of(System::Object^ obj)
{
return dynamic_cast<T^>(obj) != nullptr;
}
};
}
template <typename T> bool is_instance_of(System::Object^ obj)
{
return detail::is_instance_of_helper<T>::is_instance_of(obj);
}
一点解释:
is_instance_of_managed_helper
是一个托管类,它在运行时生成一个函数,相当于 C# 的is
运算符。它用于Expression::TypeIs
以简单的方式实现这一目标。一个这样的函数将为每个生成一次T
。
template <typename T> struct is_instance_of_helper
是一个简单地使用上述解决方案的模板结构。这是一般情况。
template <typename T> struct is_instance_of_helper<T^>
是上述结构的部分特化,dynamic_cast
用于托管句柄类型。这样,当T
可以简单地与dynamic_cast
.
template <typename T> bool is_instance_of(System::Object^ obj)
是选择要使用的模板的最终辅助函数。