Search code examples
.net-3.5inheritanceinterfacec#-3.0

Derived type cannot be implicitly converted to base interface


interface IModel {}

class MyModel : IModel {}

interface IRepo<T>
    where T: IModel { }

class Repo : IRepo<MyModel> { }

//EDIT: A smaller example
IRepo<IModel> repo = new Repo(); // Cannot implicitly convert.. An explicit convertion exists. Missing cast?

// Old example:
/*
The type 'Repo' cannot be used as type parameter 'C' in the generic type or method.
'Castle.MicroKernel.Registration.ComponentRegistration<S>.ImplementedBy<C>()'.
==> There is no implicit reference conversion from 'Repo' to 'IRepo<IModel>'.
*/
container.Register(
    Component.For<IRepo<IModel>>()
   .ImplementedBy<Repo>());

But Repo is derived from IRepo, and MyModel is derived from IModel. Why doesn't this work?

I tried adding an implicit operator on Repo, but it's not allowed to convert between interfaces..

Is this solved by the co/contra varience thing from c#4 (No, I don't have a clue what I'm talking about :) )?


Solution

  • Your intuition was right. This is a covariance issue. You see, IRepo<IModel> and IRepo<MyModel> are not the same.

    To allow for covariant types, you can fix it with the out modifier in C# 4:

    interface IRepo<out T> where T: IModel {}
    

    If you are not on C# 4 yet, you will need to tighten your usage:

    IRepo<MyModel> repo = new Repo();