Implementing interface but returning a subclass of the return type?

I am working with ASP.NET MVC in C#. I am creating service classes. I have a service interface for Driver service interfaces (IDriverService).

It has the following method definition:

Driver New();

I have two implementations of this interface which implements this method as such:

Driver New()
{
   return new Driver();
}

Driver New()
{
   return new SubclassOfDriver();
}

As you can see one implementation implements the New method by returning a base Driver, and the other is for some subclass of Driver.

The problem is by implementing the interface I have to return a 'Driver' but sometimes I want to return a 'SubclassOfDriver'. I could say that you should cast the result to the Driver you want but this is unsafe and the coder would require information about the implementation to acertain which Driver has been instantiated. What's the best way of doing this?

Thanks

Jon Skeet
people
quotationmark

You can effectively overload the return type using explicit interface implementation:

Driver IDriverService.New()
{
   return New(); // Calls the method below
}

public SubclassOfDriver New()
{
   return new SubclassOfDriver();
}

Now any code which only knows about your implementation as an implementation of the interface will see the explicit interface implementation method, and just expect a return type of Driver.

Any code which refers to the service via its concrete type will only see the second method, and expect a return type of SubclassOfDriver. For example:

SpecialFactory specialFactory = new SpecialFactory();
SubclassOfDriver subclassDriver = specialFactory.New(); // Fine
IDriverFactory generalFactory = specialFactory;
IDriver generalDriver = generalFactory.New(); // Fine
// This wouldn't compile
SubclassOfDriver invalid = generalFactory.New();

Alternatively, you might want to make your interface generic:

public interface IDriverFactory<TDriver> where TDriver : Driver
{
    TDriver New();
}

public class SpecialDriverFactory : IDriverFactory<SubclassOfDriver>
{
    public SubclassOfDriver New()
    {
        return new SubclassOfDriver();
    }
}

people

See more on this question at Stackoverflow