akc42
akc42

Reputation: 5001

How do I cast from a concrete implementation to an interface in .NET

I am tweaking a library related to vehicle journeys that for the purpose of this question has two objects. I happen to be using vb, but that is pretty irrelevent to the discussion, other than I can express the generics in the text below without the editor eating the angle brackets

The first is a Trip object which implements an interface ITrip. The second is a Hop object that implements an interface IHop. Both Trip and Hop objects have functions that are not part of the interface, but are used in the internal logic.

The ITrip interface has a read-only property, called Route, which is an IList(of IHop)

I want to implement that internally with a List(of Hop), the reason being is that the Trip objects logic needs to adjust the contents of the Hop using a Friend function.

I am having difficulty providing the code which implements the Route property, as I cannot (apparently) cast from the object to its interface. Is it possible and if so how?

Upvotes: 1

Views: 41

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064064

Casting from Hop to IHop is trivial an implicit - no syntax is required. Likewise, casting from List<Hop> to IList<Hop> is trivial and implicit.

However, you cannot simply cast a List<Hop> to a List<IHop> (or IList<...>), because they aren't compatible. The compiler is stopping you from making a mistake: a List<Hop> can only contain Hops (or subclasses of Hop) - however, a List<IHop> can contain my random SomeClass : IHop. If this cast worked, it would allow:

List<Hop> hops = ...
List<IHop> evil = hops;
evil.Add(new SomeClass()); // boom!

class SomeClass : IHop { } // but not a Hop

Basically, you will need to recreate a list of a different type. ConvertAll may be of use:

List<Hop> hops = ...
List<IHop> ihops = hops.ConvertAll(x => (IHop)x);
// or: IList<IHop> ihops = ...

You could also use (perhaps more convenient, but less efficient):

var ihops = hops.Cast<IHop>().ToList();

Additional: note that IEnumerable<out T> and IReadOnlyList<out T> can be cast directly, thanks to variance:

IReadOnlyList<Hop> hops = ...
IReadOnlyList<IHop> ihops = hops; // just works

Upvotes: 2

Related Questions