views:

317

answers:

5

I have an IRepository interface that inherits from IRepository<TObject>. I also have a SqlRepository class that inherits from SQLRepository<TObject>, which in turn implements IRepository<TObject>. Why can't I instantiate a instance of SqlRepository as an IRepository?

public class MyObject : IObject {
    ...
}

public interface IRepository<TObject> where TObject : IObject, new() {
    ...
}

public interface IRepository : IRepository<MyObject> { }

public class SqlRepository<TObject> : IRepository<TObject> where TObject : IObject, new() {
    ...
}

public class SqlRepository : SqlRepository<MyObject> { }

public class Controller {
    private IRepository _repository;

    public Controller() {
        _repository = new SqlRepository();
    }
}

The example above fails when trying to assign a new SqlRepository to _repository in the Controller class, with the following error message.

Argument '1': cannot convert from 'SqlRepository' to 'IRepository'

Which basic principle of inheritance have I failed to grasp, please help.

+10  A: 

Because IRepository is an IRepository<MyObject> and not the other way around.

Basically:

SqlRepository is a SqlRepository<MyObject>
which is an IRepository<MyObject>.
To make that work, you should either inherit IRepository<TObject> from IRepository or make SqlRepository implement IRepository depending in your intention.

This issue is not generics-specific at all. Assume:

interface IMovable { }
interface IDrivable : IMovable { } 
class Ball : IMovable { }

It's obvious that Ball is not an IDrivable while it is an IMovable.

Mehrdad Afshari
+1  A: 

SqlRepository implements IRepository<T>, not IRepository.

Daniel Earwicker
A: 

I think you need to declare it like this:

private IRepository<MyObject> _repository;
Joseph
A: 

SqlRepository does not directly inherit from IRepository, it inherits from IRepository<MyObject>.

Try having SqlRepository inherit directly from IRepository.

Randolpho
A: 

You can subclass generic types as well.

public class SqlObjectRepository : SqlRepository { ... }

But I don't think you can do that on the fly. It needs to be part of the definition of the object.