C++ cli C++/CLI问题:是否有与C“相当的;是";关键字还是我必须使用反射?

C++ cli C++/CLI问题:是否有与C“相当的;是";关键字还是我必须使用反射?,c++-cli,C++ Cli,我在MSDN上的某个地方读到,与C#的“is”关键字等效的是dynamic#u cast,但这并不是真正等效的:它不适用于值类型或泛型参数。例如,在C#中,我可以写: void MyGenericFunction<T>() { object x = ... if (x is T) ...; } 有一种更简单的方法吗?< p>可以使用安全性> /Cuff>在本地C++中使用 DyrimeCase> ,并捕获Stase::ValueStudio异常。就兼

我在MSDN上的某个地方读到,与C#的“is”关键字等效的是dynamic#u cast,但这并不是真正等效的:它不适用于值类型或泛型参数。例如,在C#中,我可以写:

void MyGenericFunction<T>()
{
    object x = ...
    if (x is T)
        ...;
}

有一种更简单的方法吗?

< p>可以使用<代码>安全性> /Cuff>在本地C++中使用<代码> DyrimeCase> <代码>,并捕获Stase::ValueStudio异常。就兼容类型而言,询问是否可以转换类型的语义可能比检查标识更广泛。实际上,您可能希望增加IsAssignableFrom的灵活性

我认为没有一个有效的方法可以与我们习惯的古老的
dynamic\u cast
成语相提并论,当然没有什么比它更简洁的了。

它在MSDN上:

简而言之,您需要编写一个帮助函数,如下所示:

template < class T, class U > 
Boolean isinst(U u) {
   return dynamic_cast< T >(u) != nullptr;
}
模板
布尔isinst(U){
返回动态_cast(u)!=nullptr;
}
这样称呼它:

Object ^ o = "f";
if ( isinst< String ^ >(o) )
    Console::WriteLine("o is a string");
对象^o=“f”; if(isinst(o)) 控制台::WriteLine(“o是一个字符串”);
虽然一个简单的解决方法是使用
safe_cast(x)
和catch
System::InvalidCastException^
,但当类型不匹配时,这会带来明显的异常处理开销(展开堆栈和所有相关的乐趣)

我试图想出一个不同的方法。虽然我不能确切地说它很简单,但它没有使用异常

#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);
}
#使用
名称空间详细信息
{
泛型ref类是\u托管\u助手密封抽象的\u实例
{
公众:
静态initonly系统::Func^是=build()的_实例_;
私人:
静态系统::Func^build()
{
使用System::Linq::Expressions::Expression;
自动参数=表达式::参数(系统::对象::类型ID);
返回表达式::Lambda(
表达式::TypeIs(param,T::typeid),
param)->Compile();
}
};
模板结构是\u助手的\u实例
{
静态布尔是(系统::对象^obj)的实例
{
返回的是受管理的辅助对象的实例::是(obj)的实例;
}
};
模板结构是\u助手的\u实例
{
静态布尔是(系统::对象^obj)的实例
{
返回动态_cast(obj)!=nullptr;
}
};
}
模板布尔是(系统::对象^obj)的实例
{
返回详细信息::是辅助对象的实例::是(obj)的实例;
}
一点解释:

  • is\u managed\u helper的实例
    是一个托管类,它在运行时生成一个函数,该函数与C的
    is
    运算符等价。它使用一种简单的方法来实现这一点。每个
    T
    将生成一个这样的函数

  • template struct是\u helper的\u instance\u
    是一个简单使用上述解决方案的模板结构。这是一般情况

  • template struct是\u helper的\u instance\u
    是上述结构的部分专门化,它对托管句柄类型使用
    dynamic\u cast
    。这样,当
    T
    可以简单地与
    dynamic\u cast
    一起使用时,我们就省去了在运行时生成代码的麻烦

  • 模板bool是(System::Object^obj)的实例。
    是选择要使用的模板的最终帮助函数


也许你误解了我的问题。我知道那篇MSDN文章。我在问题中提到了这一点。我解释了为什么它不适合我。动态#u cast并不等同于C#“as”。它只适用于参考类型。哦,应该更仔细地阅读问题。它确实适用于泛型类型,但不适用于值类型。C#的
as
也不适用于值类型:
dynamic_cast
完全等同于
as
。使用
safe\u cast
转换为值类型。语义与C#的语义等价:对值类型的错误转换抛出异常,对引用类型的错误转换返回
null
Object ^ o = "f";
if ( isinst< String ^ >(o) )
    Console::WriteLine("o is a string");
#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);
}