C#中IsAssignableFrom和"is"关键字的使用

52

在尝试学习Unity时,我一直看到 MVC 中重写 GetControllerInstance 的以下代码:

if(!typeof(IController).IsAssignableFrom(controllerType)) { ... }

这对我来说似乎是一种相当复杂的方式,基本上是在编写

if(controllerType is IController) { ... }

我理解isIsAssignableFrom之间存在微妙的区别,即IsAssignableFrom不包括强制类型转换,但我很难理解这种差异在实际场景中的影响。

在何时选择IsAssignableFromis更重要?在GetControllerExample中会有什么区别?

if (!typeof(IController).IsAssignableFrom(controllerType))
      throw new ArgumentException(...);
return _container.Resolve(controllerType) as IController;
4个回答

81

这不是同样的东西。

if(controllerType is IController)

always总是会评估为false,因为controllerType始终是一个Type,而Type永远不是一个IController

is运算符用于检查一个实例是否与给定类型兼容。

IsAssignableFrom方法用于检查一个Type是否与给定类型兼容。


啊,好的,现在差异很明显了。我应该早点发现! - fearofawhackplanet
那么我的猜测是,如果TU是泛型类型,那么typeof(T).IsAssignableFrom(typeof(U))new T() is U是相同的吗? - orad
2
不过,它与 new U() is T 相同。T 将是基本类型。我总是被这个绊倒。我只记得 IsAssignableFromis 操作符相反。 - Jordan

21

typeof(IController).IsAssignableFrom(controllerType)测试一个Type是否可以赋值给接口。is运算符用于测试实例是否可以赋值给接口。


16
< p > is 关键字仅适用于实例,而 Type.IsAssignableFrom() 仅适用于类型。

示例:is

string str = "hello world";
if(str is String)
{
    //str instance is of type String
}
请注意,str是一个实例而不是类型。
IsAssignableFrom()的示例。
string str = "hello world";
if(typeof(Object).IsAssignableFrom(str.GetType()))
{
    //instances of type String can be assigned to instances of type Object.
}

if(typeof(Object).IsAssignableFrom(typeof(string)))
{
    //instances of type String can be assigned to instances of type Object.
}

请注意,IsAssignableFrom() 方法的参数不是字符串实例本身,而是表示字符串类型的 Type 对象。


5

一个显著的区别是'is'在测试继承或接口实现时具有直观意义,而IsAssignableFrom则毫无道理。Type.IsAssignableFrom方法的名称在测试继承或检测接口实现时含糊且令人困惑。以下包装器可用于此类目的,可以使应用程序代码更加直观、易读:

    public static bool CanBeTreatedAsType(this Type CurrentType, Type TypeToCompareWith)
    {
        // Always return false if either Type is null
        if (CurrentType == null || TypeToCompareWith == null)
            return false;

        // Return the result of the assignability test
        return TypeToCompareWith.IsAssignableFrom(CurrentType);
    }

然后,我们可以使用更易懂的客户端语法,例如:
    bool CanBeTreatedAs = typeof(SimpleChildClass).CanBeTreatedAsType(typeof(SimpleClass));
    CanBeTreatedAs = typeof(SimpleClass).CanBeTreatedAsType(typeof(IDisposable));

使用此方法而不是“is”关键字的优势在于,它可以在运行时用于测试未知的、任意的类型,而“is”关键字(以及通用类型参数)需要对特定类型进行编译时知识。

我不认为 IsAssignableFrom 完全没有直觉性。在多态类型系统中,任何类型都可以从其子类型中分配一个值,也就是说,你可以做这样的事情:SimpleBaseClass myVar = new SimpleChildClass()IsAssignableFrom 告诉你这样的多态赋值是否合法,因此告诉你一个类型是否是另一个类型的子类型或相等类型。 - zstewart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接