Consider an example:
I have an interface like this. I need this interface to be covariant - meaning I have to declare my generic as "out" and use IEnumerable instead of list - and that's all. I'll use this just to simply get the elements that I need - nothing to insert.
public interface IFoo<out T>
{
IEnumerable<T> Items { get; }
}
And then I have my concrete class declared like this:
public class Foo : IFoo<Item>
{
// I have an error here : Type IList doesn't match the expected type IEnmerable
IList<Item> Items { get; set; }
}
And I'm wondering why is that not possible? I mean IList inherits from IEnumerable and this type of code works completely fine.
public IEnumerable<Item> GetItems()
{
return new List() { new Item())};
}
Why it can be done? What are the workarounds?
My only solution is that I could just create additional property or method Like this
public IEnumerable<Item> GetEnumerableItems()
{
return Items;
}
But it seems too hacky for me. I thinking there could be a cleaner solution.
CodePudding user response:
This is not supported by the runtime. If you are implementing an interface which has a property that returns a particular type, you must match that return type exactly in your implementation.
Return Type Covariance was added in C# 9, but doesn't apply here (see @JeroenMostert's comment).
You can work around this by using explicit interface implementation:
public class Foo : IFoo<Item>
{
IList<Item> Items { get; set; }
IEnumerable<Item> IFoo<Item>.Items => Items;
}
Consumers which have a Foo
can access Foo.Items
and get an IList<Item>
. Consumers which just have an IFoo<Item>
can instead access IFoo<Item>.Items
, and will get back an IEnumerable<Item>
.