Generic parameter – using a concrete type compiles, but an implemented interface does not

  • A+
Category:Languages

Given these interfaces and classes...

public interface IPage {     string PageTitle { get; set; }     string PageContent { get; set; } }   public abstract class Page     : IPage {     public string PageTitle { get; set; }     public string PageContent { get; set; } }   public class AboutPage     : Page     , IPage { }   public interface IPageAdminViewModel<out T>     where T : IPage {     IEnumerable<T> Pages { get; } }   public abstract class PageAdminViewModel<T>     : IPageAdminViewModel<T>     where T: IPage {     public IEnumerable<T> Pages { get; set; } } 

Why does using IPage as an interface type parameter not compile....

public class AboutPageAdminViewModel     : PageAdminViewModel<AboutPage>     , IPageAdminViewModel<IPage> // ERROR HERE - I realise this declaration is not required, just indicating where the error is (not) { } 

'AboutPageAdminViewModel' does not implement interface member 'IPageAdminViewModel<IPage>.Pages'. 'PageAdminViewModel<AboutPage>.Pages' cannot implement 'IPageAdminViewModel<IPage>.Pages' because it does not have the matching return type of 'IEnumerable<IPage>'.

....when using the concrete class AboutPage does?

public class AboutPageAdminViewModel     : PageAdminViewModel<AboutPage>     , IPageAdminViewModel<AboutPage> // NO ERROR - I realise this declaration is not required, just indicating where the error is (not) { } 

Essentially, I don't understand why the return type of IEnumerable<IPage> does not match the return type of IEnumerable<AboutPage>.

I would like to create a method that takes IPageAdminViewModel<IPage> as an argument. I am wondering how / if I can make AboutPageAdminViewModel fit that requirement.

 


Picking up on Eric’s example:

class Animal {} class Tiger : Animal {}  interface ICage {      Animal GetAnimal(); }  class TigerCage : ICage {      //Won’t compile     public Tiger GetAnimal() =>          new Tiger(); } 

You can solve this by implementing both an explicit interface member and a strongly typed method, one of which will delegate to the other to avoid code duplication:

class TigerCage: ICage {     Animal ICage.GetAnimal() => GetAnimal();     public Tiger GetAnimal() => new Tiger(); } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: