C++/CLI-问题:是否有与 C# 的“is”等价的命令? 关键字还是我必须使用反射?
我在 MSDN 上读到,与 C# 的“is”关键字等效的是dynamic_cast,但这并不是真正等效的:它不适用于值类型或泛型参数。 例如,在 C# 中,我可以编写:
void MyGenericFunction<T>()
{
object x = ...
if (x is T)
...;
}
如果我尝试“等效”C++/CLI:
generic<class T>
void MyGenericFunction()
{
object x = ...
if (dynamic_cast<T>(x))
...;
}
我收到编译器错误“错误 C2682:无法使用 'dynamic_cast' 从 'System::Object ^' 转换为 'T'”。
我唯一能想到的就是使用反射:
if (T::typeid->IsAssignableFrom(obj->GetType()))
有没有更简单的方法来做到这一点?
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 generic parameters. For example in C# I can write:
void MyGenericFunction<T>()
{
object x = ...
if (x is T)
...;
}
If I try the "equivalent" C++/CLI:
generic<class T>
void MyGenericFunction()
{
object x = ...
if (dynamic_cast<T>(x))
...;
}
I get a compiler error "error C2682: cannot use 'dynamic_cast' to convert from 'System::Object ^' to 'T'".
The only thing I can think of is to use reflection:
if (T::typeid->IsAssignableFrom(obj->GetType()))
Is there a simpler way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
它位于 MSDN 上:
如何:在 C++ 中实现 is 和 as C# 关键字
简而言之,您需要编写一个像这样的辅助函数:
并像这样调用它:
It's on MSDN:
How to: Implement is and as C# Keywords in C++
In a nutshell, you need to write a helper function like so:
and call it like this:
您可以在本机 C++ 中使用
dynamic_cast
的地方使用safe_cast
并捕获 System::InvalidCastException。 就兼容类型而言,询问是否可以转换类型的语义可以选择比检查身份更广泛的类型。 您可能实际上想要 IsAssignableFrom 增加的灵活性。我认为没有一个有效的方法可以与我们习惯的旧的
dynamic_cast
习惯用法等效,当然也没有比它更紧凑的方法。You can use
safe_cast
where you would usedynamic_cast
in native C++ and trap the System::InvalidCastException. In terms of compatible types the semantics of asking if you can convert types could pick up a broader range of types than checking identity. You may actually want the added flexibility of IsAssignableFrom.I don't think there's an efficient equivalent to the good old
dynamic_cast
idiom we're used to, certainly nothing as compact.虽然一个简单的解决方法是使用
safe_cast(x)
并捕获System::InvalidCastException^
,但这具有明显的异常处理开销(展开堆栈和所有相关的乐趣)当类型不匹配时。我尝试想出一种不同的方法。 虽然我不会确切地称其为“简单”,但它在不使用异常的情况下完成了其工作。
一些解释:
is_instance_of_driven_helper
是一个托管类,它在运行时生成一个函数,相当于 C# 的is
运算符。 它使用Expression::TypeIs
以简单的方式实现这一点。 对于每个
T
都会生成一个这样的函数一次。模板 <类型名称 T> struct is_instance_of_helper
是一个模板结构,它仅使用上述解决方案。 这是一般情况。模板 <类型名称 T> struct is_instance_of_helper
是上述结构的部分特化,它使用dynamic_cast
来表示托管句柄类型。 这样,当T
可以简单地与dynamic_cast
一起使用时,我们就可以省去在运行时生成代码的麻烦。模板 <类型名称 T> bool is_instance_of(System::Object^ obj)
是最终的辅助函数,它将选择要使用的模板。While a simple workaround would be to use
safe_cast<T>(x)
and catchSystem::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.
A bit of explanation:
is_instance_of_managed_helper
is a managed class which generates a function at runtime giving the equivalent of C#'sis
operator. It usesExpression::TypeIs
to achieve this in a simple way. One such function will be generated once for everyT
.template <typename T> struct is_instance_of_helper
is a template struct which simply uses the above solution. This is the general case.template <typename T> struct is_instance_of_helper<T^>
is a partial specialization of the above struct which usesdynamic_cast
for managed handle types. This way, we'll spare ourselves the trouble of generating code at runtime whenT
can simply be used withdynamic_cast
.template <typename T> bool is_instance_of(System::Object^ obj)
is the final helper function which will choose the template to use.