Seamless Delegate Type Casting

November 04, 2011

In Seamless Generic Type Casting, we saw how the in and out keywords can make our generic interfaces polite with respect to casting. A List<string> can be treated as an IEnumerable<object> because a) all strings are objects and b) IEnumerable is declared with the out keyword. Now, we'll see how these keywords can be applied to delegate types in addition to interface types.

Suppose we have a a basic hierarchy of entity classes:

Also, suppose we find ourselves creating/persisting many instances of these in our integration tests, and we create a delegate type with some helper methods for doing so:

In our integration tests, we may use this to quickly get some sample employees into our database:

As we write some tests, we realize that we need some of our sample employees to be populated differently:

Surprise! This won't even compile. The compiler can't assign our EntityCreator<SalesPerson> to the expected type EntityCreator<Employee>. That's strange, since we know that any SalesPerson it ever makes will obviously be an Employee. As we saw with similar situations around interfaces, we need to use the out keyword when we define the delegate type, promising to the compiler that the T will only appear in the return value. Armed with this additional promise, the compiler can safely treat all EntityCreator<FieldTechnician> as EntityCreator<Employee>. With the following change, the example compiles as expected: