1

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.

Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
kim3er
  • 6,306
  • 4
  • 41
  • 69
  • I resolved the issue by making SqlRespository implement IRepository (public class SqlRepository : SqlRepository, IRepository { }), which seems a little superfluous but I guess I understand the logic. – kim3er Jul 06 '09 at 20:09

5 Answers5

10

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
  • 414,610
  • 91
  • 852
  • 789
1

SqlRepository implements IRepository<T>, not IRepository.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
0

I think you need to declare it like this:

private IRepository<MyObject> _repository;
Joseph
  • 25,330
  • 8
  • 76
  • 125
0

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

Try having SqlRepository inherit directly from IRepository.

Randolpho
  • 55,384
  • 17
  • 145
  • 179
0

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.