Использование IsAssignableFrom и ключевое слово "is" в С#
При попытке узнать Unity, я продолжаю видеть следующий код для переопределения GetControllerInstance
в MVC:
if(!typeof(IController).IsAssignableFrom(controllerType)) { ... }
это кажется мне довольно запутанным способом писать в основном
if(controllerType is IController) { ... }
Я понимаю, что существуют тонкие различия между is
и IsAssignableFrom
, т.е. IsAssignableFrom
не включает преобразования преобразования, но я изо всех сил стараюсь понять последствия этой разницы в практических сценариях.
Когда это целесообразно выбрать IsAssignableFrom
над is
? Какая разница в GetControllerExample
?
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(...);
return _container.Resolve(controllerType) as IController;
Ответы
Ответ 1
Это не то же самое.
if(controllerType is IController)
всегда будет оцениваться с помощью false
, так как controllerType
всегда является Type
, а a Type
никогда не является IController
.
Оператор is
используется для проверки совместимости экземпляра с данным типом.
Метод IsAssignableFrom используется для проверки совместимости Тип с данным типом.
Ответ 2
typeof(IController).IsAssignableFrom(controllerType)
проверяет a Type
на интерфейс. Оператор is
проверяет экземпляр интерфейса.
Ответ 3
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() не является экземпляром String, это объект Type, представляющий тип String.
Ответ 4
Заметная разница также в том, что "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 заключается в том, что его можно использовать во время выполнения для проверки неизвестных произвольных типов, тогда как ключевое слово "is" (и общий параметр типа) требует знания времени компиляции определенных типов.