0

I have some interfaces and classes for domains and elements:

interface IElement {}
class FloatElement : IElement {}

interface IDomain<T> where T: IElement {}
class FloatDomain : IDomain<FloatElement>
{
    public static readonly FloatDomain Instance = new FloatDomain();
}

I wrote this

IDomain<IElement> foo = FloatDomain.Instance;

but got an error:

(CS0266) "Cannot implicitly convert type [...]. An explicit conversion exists (are you missing a cast?)"

(Note that, despite the hint "An explicit conversion exists", FloatDomain.Instance as IDomain<IElement> will return null.)

I already found out that I can work around this problem by making FloatDomain also implement IDomain<IElement>. But I would like to know why this workaround is necessary!

In my understanding, FloatElement is a more specialized version of IElement, i.e. I can implicitly convert FloatElement to IElement. Because of that, IDomain<FloatElement> is a more specialized version of IDomain<IElement>, i.e. I should also be able to implicitly convert IDomain<FloatElement> to IDomain<IElement>.

Or in other words: in my understanding, IDomain<IElement> is like a base class for all other IDomain<T> where T implements IElement, because T=IElement is the most general possible case.

Can you point me to my error of reasoning?

Kjara
  • 2,504
  • 15
  • 42

1 Answers1

3

What you're trying to do is called variance. In C# interfaces are not variant by default, and that's why you're getting compile errors. You can mark your interface as covariant or contravariant explicitly to make it work:

interface IDomain<in T> where T: IElement {}

interface IDomain<out T> where T: IElement {}

See Variance in Generic Types for more details.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263