1

Given this code:

public interface ITagModel { }

public interface ITemplate {
    ITagModel Model { get; set; }
}

public class EmailTag : ITagModel { }

public class EmailTest : ITemplate {
    public EmailTag Model { get; set; }
}

I am being told that the Type of EmailTag (inside EmailClass) cannot implement the Property Model because it is not the type ITagModel.

It is inheriting ITagModel....so why won't this work? What can I do to accomplish what I'm looking for?

James P. Wright
  • 8,991
  • 23
  • 79
  • 142

2 Answers2

5

C# doesn't support covariant return.

e.g.

public class Base { }
public class Derived : Base { }

public class Component
{
    public virtual Base GetComponent()
    {
        return new Base();
    }
}

public class DerviedComponent : Component
{
    public override Dervied GetComponent()
    {
        return new Derived();
    }
}

So you'll need to abstract the return type and constrain it to your interface. That way any implementation will need to supply an ITagModel.

public interface ITagModel { }

public interface ITemplate<TModel>
    where TModel : ITagModel
{
    TModel Model { get; set; }
}

public class EmailTag : ITagModel { }

public class EmailTest : ITemplate<EmailTag> {
    public EmailTag Model { get; set; }
}
Community
  • 1
  • 1
Dustin Kingen
  • 20,677
  • 7
  • 52
  • 92
2

It sounds like your ITemplate interface should be generic:

public interface ITemplate<TModel> where TModel : ITagModel
{
    TModel Model { get; set; }
}

Then:

public class EmailTest : ITemplate<EmailTag>
{
    public EmailTag Model { get; set; }
}

Imagine if your current code worked. I could then write:

ITemplate template = new EmailTest();
template.Model = new SomeOtherModel();

... and you wouldn't want that. (Basically, you'd be violating type safety.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194