C++/CLI-Question: Is there an equivalent to the C# “is” keyword or do I have to use reflection?

后端 未结 3 1122
不知归路
不知归路 2021-01-01 23:38

I\'ve read somewhere on MSDN that the equivalent to C#\'s \"is\" keyword would be dynamic_cast, but that\'s not really equivalent: It doesn\'t work with value types or with

3条回答
  •  南笙
    南笙 (楼主)
    2021-01-01 23:56

    While a simple workaround would be to use safe_cast(x) and catch System::InvalidCastException^, this has the obvious overhead of exception handling (unrolling the stack and all the related fun) when the type doesn't match.

    I tried to come up with a different approach. While I wouldn't exactly call it simple, it does its job without using exceptions.

    #using 
    
    namespace detail
    {
        generic  ref class is_instance_of_managed_helper sealed abstract
        {
        public:
            static initonly System::Func^ is_instance_of = build();
    
        private:
            static System::Func^ build()
            {
                using System::Linq::Expressions::Expression;
                auto param = Expression::Parameter(System::Object::typeid);
                return Expression::Lambda^>(
                    Expression::TypeIs(param, T::typeid),
                    param)->Compile();
            }
        };
    
        template  struct is_instance_of_helper
        {
            static bool is_instance_of(System::Object^ obj)
            {
                return is_instance_of_managed_helper::is_instance_of(obj);
            }
        };
    
        template  struct is_instance_of_helper
        {
            static bool is_instance_of(System::Object^ obj)
            {
                return dynamic_cast(obj) != nullptr;
            }
        };
    }
    
    template  bool is_instance_of(System::Object^ obj)
    {
        return detail::is_instance_of_helper::is_instance_of(obj);
    }
    

    A bit of explanation:

    • is_instance_of_managed_helper is a managed class which generates a function at runtime giving the equivalent of C#'s is operator. It uses Expression::TypeIs to achieve this in a simple way. One such function will be generated once for every T.

    • template struct is_instance_of_helper is a template struct which simply uses the above solution. This is the general case.

    • template struct is_instance_of_helper is a partial specialization of the above struct which uses dynamic_cast for managed handle types. This way, we'll spare ourselves the trouble of generating code at runtime when T can simply be used with dynamic_cast.

    • template bool is_instance_of(System::Object^ obj) is the final helper function which will choose the template to use.

提交回复
热议问题