检查类型TA是否可以在运行时强制转换为TB? (考虑的不仅仅是继承)

时间:2012-10-05 15:24:55

标签: c# .net cil

所以我知道这有效:

class A
{
}
class B : A
{       
}

[Test]
public void CanCast()
{
    Assert.That(typeof(A).IsAssignableFrom(typeof(B)));
    Assert.That(!typeof(B).IsAssignableFrom(typeof(A)));
}

但是,假设这两种类型是Int32和Int64。

在运行时,我可以将Int32值转换为Int64变量,但不是相反。如何在运行时检查这种类型的转换兼容性? (IsAssignableFrom不适用于此,它总是为Int32和Int64提供false)

编辑:我不能简单地尝试施放,因为我没有这些类型的任何值,我问的是有两种类型A和B,没有两个值的假设情景a和b。

2 个答案:

答案 0 :(得分:6)

对于非基本类型,您可以反映并检查是否在支持转换的任一类型上都有op_Implicit方法。 IL实际上并不支持真正的运算符重载,所以它纯粹是C#的常规系统,用于识别运算符重载。如果它是从C#中的运算符重载定义创建的,则该方法也将标记为IsSpecialName。

对于primitive types(如Int32和Int64),最简单的选项是硬编码各种情况,因为转换是通过原始IL操作码而不是通过方法。但是,只有少数基本类型,因此创建一个方法来检查每种基本类型的所有可能性并不困难。

一方面注意,因为您的示例特别提到了原始值类型,请注意隐式“转换”(在C#中)的存在并不意味着所有“强制转换”都可以工作。 C#强制转换操作(T)x也可以表示'将x中的值解包为T'。如果x包含一个盒装的Int32并且您尝试(Int64)x,那么这将在运行时失败,即使您可以隐式地将Int32“转换”为Int64。有关为什么拆箱以这种方式工作的详细信息,请参阅Eric Lippert

答案 1 :(得分:-1)

一种(不太优雅)的方法是简单地尝试它 - 将您的尝试包装在try / catch中,如果捕获异常则将Assert设为false。