Mohsen Afshin
Mohsen Afshin

Reputation: 13436

Interface Cast Type Safety

Type safety prevents unwanted casting during compile-type. How can one achieve the same compile-time type safety for inherited interfaces?

public interface IBase { }
public interface IFoo : IBase { }
public interface IBar { }


public class Base { }
public class Foo : Base { }
public class Bar { }

public class Test
{
    public void TestInterface()
    {
        IBase item = null;

        IFoo foo = item as IFoo;

        // How to get an error?
        IBar bar = item as IBar;
    }

    public void TestClass()
    {
        Base item = null;

        Foo foo = item as Foo;

        // Error since Bar is not derived from Base
        Bar bar = item as Bar;
    }
}

Upvotes: 4

Views: 125

Answers (5)

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64923

Compiler will be able to throw an error if you try to compile the following code:

IFoo foo = null;
IBar bar = foo; // Invalid cast at compile-time

When you use as operator, you're telling the compiler to leave the cast as is and let the runtime determine if the cast is valid or not, and if it's not valid it sets null.

If you want compile-time errors for these situations you should take a look at Code Contracts and you can always use an assertion:

  IFoo foo = new Foo();
  IBar bar = foo as IBar;
  Contract.Assert(bar != null);

...and enable static contract checking and Code Contracts compiler will throw warnings or errors depending on your project settings during compile-time:

Code contracts include classes for marking your code, a static analyzer for compile-time analysis, and a runtime analyzer. The classes for code contracts can be found in the System.Diagnostics.Contracts namespace.

Upvotes: 1

Patrick Hofman
Patrick Hofman

Reputation: 156958

You can't. The compiler doesn't know that the type that implements IBase and IFoo doesn't also implement IBar. It isn't class inheritance where it is impossible to derive from more than one.

What if item was an instance of this class?

public class BarAndFoo : IBar, IFoo { }

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500375

You can't, and shouldn't - because it might not be an error. Consider an extra class:

class BarBase : IBase, IBar
{
}

Now:

IBase item = new BarBase();
IBar bar = item as IBar;

That will leave bar as a non-null reference - so why would you want it to be a compile-time error? Note that the compiler shouldn't/doesn't take notice of:

  • How you actually initialized item
  • Whether or not there happen to be any classes that implement IBase and IBar

It will take notice of whether such a conversion could ever be valid. Consider:

public sealed class Sealed {}
public interface IFoo {}

Sealed x = null;
IFoo foo = x as IFoo; // Error

Here there is no possible non-null value of Sealed that could implement IFoo, because there can't be any subclasses of Sealed implementing the interface... so the compiler gives an error.

Upvotes: 2

Jakub Lortz
Jakub Lortz

Reputation: 14896

Multiple inheritance is not allowed in C#, so it is not possible that a class derived from Base can be cast to Bar.

However a class can implement several interfaces. So it is possible that an object referenced by IBase reference is an instance of a class that also implements IBar. In that case, the cast will be valid.

public class BarFoo : IBar, IFoo { }

IBase item = new BarFoo();
IFoo foo = item as IFoo;
IBar bar = item as IBar;

Upvotes: 1

Crozin
Crozin

Reputation: 44376

Keep in mind that the item object can be a class that implements both interfaces (IBase and IBar) so that kind of cast is perfectly fine.

class MyImplementation : IBase, IFoo, IBar {
}

IBase x = new MyImplementation();
IBar bar = x as IBar; // valid

Upvotes: 0

Related Questions