Home > OS >  Having IEnumerable<T> declared inside interface while having IList<T> declared in concre
Having IEnumerable<T> declared inside interface while having IList<T> declared in concre

Time:03-09

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;
}

SharpLab.

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>.

  • Related