The is operator is used to dynamically check if the run-time type of an object is compatible with a given type. The result of the operation e is T, where e is an expression and T is a type, is a boolean value indicating whether e can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. The operation is evaluated as follows: If the compile-time type of e is the same as T, or if an implicit reference conversion (13.1.4) or boxing conversion (13.1.5) exists from the compile-time type of e to T: If e is of a reference type, the result of the operation is equivalent to evaluating e != null. If e is of a value type, the result of the operation is true.
Otherwise, if an explicit reference conversion (13.2.3) or unboxing conversion (13.2.4) exists from the compile-time type of e to T, a dynamic type check is performed: If the value of e is null, the result is false. Otherwise, let R be the run-time type of the instance referenced by e. If R and T are the same type, if R is a reference type and an implicit reference conversion from R to T exists, or if R is a value type and T is an interface type that is implemented by R, the result is true. Otherwise, the result is false.
Otherwise, no reference or boxing conversion of e to type T is possible, and the result of the operation is false.
Note that the is operator only considers reference conversions, boxing conversions, and unboxing conversions. Other conversions, such as user defined conversions, are not considered by the is operator.