注意:这不是"Use of IsAssignableFrom and “is” keyword in C#"的重复。其他问题询问
typeof(T).IsAssignableFrom(type))
,其中type
不是object
但是Type
。这似乎微不足道 - 我可以听到你说,“只需致电
x.GetType()
!” - 但是由于下面提到的与COM相关的角落情况,该调用会导致问题,这就是我要求重写的原因。
......或者是否存在罕见的特殊情况,两者可能会产生不同的结果?
我偶然发现了表格的类型检查:
typeof(TValue).IsAssignableFrom(value.GetType())
其中TValue
是泛型类型参数(没有任何约束),value
是object
。
我不完全确定将上述内容重写为以下内容是否安全:
value is TValue
据我目前所知,这两个测试是相同的,但COM对象除外。 is
应该触发正确的QueryInterface
,而IsAssignableFrom
可能会被__ComObject
RCW包装类型混淆并报告误报。
is
与IsAssignableFrom
的显示用途之间是否存在其他差异?
答案 0 :(得分:7)
is
和IsAssignableFrom
返回不同结果的情况更多,而不仅仅是您为COM对象提到的结果。对于具有 ElementType1 和 ElementType2 类型元素的数组类型对,其中两种元素类型的底层类型是相同大小但具有相反符号的整数类型,则
typeof(ElementType1[]).IsAssignableFrom(typeof(ElementType2[]))
返回 true ,但
new ElementType2[0] is ElementType1[]
返回 false
具体来说,这包括具有这些元素类型对的数组:
byte / sbyte , short / ushort , int / uint , long / ulong
IntPtr / UIntPtr
枚举类型与整数类型或其他枚举类型的任意组合,只要底层类型具有相同的大小
32位进程中 IntPtr / UIntPtr / int / uint 的任意组合< / p>
64位进程中 IntPtr / UIntPtr / long / ulong 的任意组合< / p>
这是由于C#和CLR类型系统的差异,如
中所述上述所有情况下is
和IsAssignableFrom
的不同结果都是因为new ElementType2[0] is ElementType1[]
C#编译器只是在编译时发出False
(因为它看到了不能将例如int []强制转换为uint [],因为这些是与C#perspective完全不同的类型),完全省略任何运行时类型检查。幸运的是,将数组转换为对象((object)new ElementType2[0]) is ElementType1[]
会强制编译器发出isinst
IL指令,该指令执行运行时类型检查,返回与IsAssignableFrom
一致的结果。对于目标类型是泛型参数的情况也是如此,因为它的类型在编译时是未知的,并且C#编译器必须发出isinst
。因此,如果您打算仅在目标类型为通用参数的地方(如问题标题中所示)将IsAssignableFrom
替换为is
,我相信这些差异并不适合您。
答案 1 :(得分:4)
static void Main(string[] args)
{
int? bob = null;
Test(bob);
}
private static void Test<T>(T bob)
{
Console.WriteLine(bob is T);
Console.WriteLine(typeof(T).IsInstanceOfType(bob));
Console.WriteLine(typeof(T).IsAssignableFrom(bob.GetType()));
Console.ReadLine();
}
是一个示例,它们的行为略有不同(因为bob为null)。 https://stackoverflow.com/a/15853213/34092可能会引起关注。
除此之外(以及您提及的其他例外情况),它们似乎相同。