## Why is this an issue?

To check the type of an object there are several options:

- `expr is SomeType` or `expr.GetType() == typeof(SomeType)` if the type is known at compile time,
- `typeInstance.IsInstanceOfType(expr)` if the type is calculated during runtime.

If runtime calculated `Type`s need to be compared:

- `typeInstance1.IsAssignableFrom(typeInstance2)`.

Depending on whether the type is returned by a `GetType()` or `typeof()` call, the `IsAssignableFrom()` and `IsInstanceOfType()` might be simplified. Similarly, if the type is `sealed`, the type comparison with `==` can be converted to an `is` call. Simplifying the calls also make `null` checking unnecessary because both `is` and `IsInstanceOfType` performs it already.

Finally, utilizing the most concise language constructs for type checking makes the code more readable, so

- `expr as T != null` checks should be simplified to `expr is T`, and
- `expr is T` should be converted to `expr != null`, when `expr` is of type `T`.

### Noncompliant code example

    class Fruit { }
    sealed class Apple : Fruit { }

    class Program
    {
      static void Main()
      {
        var apple = new Apple();
        var b = apple != null && apple.GetType() == typeof (Apple); // Noncompliant
        b = typeof(Apple).IsInstanceOfType(apple); // Noncompliant
        if (apple != null)
        {
          b = typeof(Apple).IsAssignableFrom(apple.GetType()); // Noncompliant
        }
        var appleType = typeof (Apple);
        if (apple != null)
        {
          b = appleType.IsAssignableFrom(apple.GetType()); // Noncompliant
        }

        Fruit f = apple;
        if (f as Apple != null) // Noncompliant
        {
        }
        if (apple is Apple) // Noncompliant
        {
        }
      }
    }

### Compliant solution

    class Fruit { }
    sealed class Apple : Fruit { }

    class Program
    {
      static void Main()
      {
        var apple = new Apple();
        var b = apple is Apple;
        b = apple is Apple;
        b = apple is Apple;
        var appleType = typeof(Apple);
        b = appleType.IsInstanceOfType(apple);

        Fruit f = apple;
        if (f is Apple)
        {
        }
        if (apple != null)
        {
        }
      }
    }

### Exceptions

Calling `GetType` on an object of `Nullable<T>` type returns the underlying generic type parameter `T`, thus a comparison with `typeof(Nullable<T>)` can’t be simplified to use the `is` operator, which doesn’t make difference between `T` and `T?`.

    int? i = 42;
    bool condition = i.GetType() == typeof(int?); // false;
    condition = i is int?; // true

No issue is reported on the following expressions:

- `expr is T` when either operand of the `is` operator is a value type. In that case CS0183 or CS0184 reports
- `expr is object`, as this is a common and efficient pattern to do null checks