Search code examples
c#roslyncompiler-warnings

No CS0184 warning for impossible check


Why does testB in this example not give a "warning CS0184: The given expression is never of the provided ('MyClass2') type" the same way that testA does?

class Program
{
    void Main()
    {
        var a = new MyClass1();
        var b = (IMyInterface)new MyClass1();
        
        //Get a CS0184 Warning on this line
        var testA = a is MyClass2;
        
        //No warning on this line
        var testB = b is MyClass2;
                
    }
}

interface IMyInterface
{
}

class MyClass1 : IMyInterface
{
}

class MyClass2
{
}

Solution

  • Because the type of b is IMyInterface. The compiler does not analyse the code to find the actual runtime type of the object you assigned to b.

    It is possible for a variable of type IMyInterface to be is MyClass2. For example, if b refers to an instance of MyClass3:

    class MyClass3: MyClass2, IMyInterface {}
    

    Of course, if MyClass2 is sealed, MyClass3 cannot exist, so b can never be is MyClass2 in that case, and you get the warning as expected.

    This is also why it is possible to cast an expression of a non-sealed class type to any interface type, e.g.

    var a = new MyClass2();
    // this compiles, but throws an exception at runtime, of course
    var b = (IMyInterface)a;
    

    Even if MyClass2 doesn't implement IMyInterface, at runtime it may be referring to some subclass that does implement IMyInterface.