Использование IsAssignableFrom и ключевого слова "is" в C # - PullRequest
51 голосов
/ 10 июня 2010

При попытке выучить 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;

Ответы [ 4 ]

80 голосов
/ 10 июня 2010

Это не то же самое.

if(controllerType is IController)

будет всегда оценивать как false, поскольку controllerType всегда является Type, а Type никогда не является IController.

Оператор is используется для проверки совместимости экземпляра с данным типом.

Метод IsAssignableFrom используется для проверки совместимости Type с данным типом.

21 голосов
/ 10 июня 2010

typeof(IController).IsAssignableFrom(controllerType) проверяет Type на соответствие интерфейсу. Оператор is проверяет экземпляр на соответствие интерфейсу.

16 голосов
/ 10 июня 2010

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.

5 голосов
/ 26 октября 2011

Заметным отличием является также то, что «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" (и универсальный параметр типа) требует знания во время компиляции. определенных типов.

...