1

I have an interface ID, which is derived from another interface IB.

public interface IB
{
    int Num { get; }
}

public interface ID : IB
{

}

Let's say we have a class that implements ID:

public class DImpl : ID
{
     public int Num { get; set; }
}

I know that I can call a function that receives IB with a variable that is held as ID.

public void FuncOfIB(IB b)
{
     // do something
}

public static void Main()
{
     ID d = new DImpl();
     FuncOfIB(d); // Works
}

I would like to call a function that receives a List<IB> as a parameter:

void ProcessListOfIB(List<IB> list)
{
   // Some code
}

But it seems that I can't call this function with List<ID>.

public static void Main()
{
     List<ID> listID = new List<ID>();
     ProcessListOfIB(listID); // Doesn't work
}

Does anyone know why? And how can I fix it? thank you.

Edit: I need the function ProcessListOfIB to remove an item from the list, so copying doesn't solve my problem...

Noam Ohana
  • 186
  • 14
  • Possible duplicate of [Casting List<> of Derived class to List<> of base class](https://stackoverflow.com/questions/3720751/casting-list-of-derived-class-to-list-of-base-class) – ProgrammingLlama Mar 07 '19 at 09:13
  • 1
    You can workaround this with linq: `listD.Cast().ToList()` – Aleks Andreev Mar 07 '19 at 09:14
  • The problem is that I want the function ProcessListOfIB() will delete a member in the original list. I'll edit my original post – Noam Ohana Mar 07 '19 at 09:20
  • 1
    A `List` allows you to add items, so potentially `ProcessListOfIB` could call `list.Add(x)`, where `x` is of type `IB`. This would mean your list would no longer be entirely composed of `ID` items. That in a nutshell is why the implicit cast is not permitted. – Gary McGill Mar 07 '19 at 09:20
  • Well, does the code in your ProcessListOfIB method really require a List? Could it perhaps be happy with a method parameter of type IEnumerable instead? If your ProcessListOfIB method could work with an IEnumerable instead of a List, then use a method parameter using IEnumerable. Not only would the method be usable with other collection types this way, your problem would simply disappear due to the generic type parameter in IEnumerable being [covariant](https://learn.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance). –  Mar 07 '19 at 09:21
  • I need to remove an item from the original list, so IEnumerable doesn't help... – Noam Ohana Mar 07 '19 at 09:23

3 Answers3

4

You can create Generic method and limit type to IB:

void ProcessListOfIB<T>(List<T> list) where T:IB
{
    // Some code
}
Pablo notPicasso
  • 3,031
  • 3
  • 17
  • 22
1

If you only need to loop through the collection (as opposed to modify it):

void ProcessListOfIB(IEnumerable<IB> list)
{
    // Some code
}
vc 74
  • 37,131
  • 7
  • 73
  • 89
0

List is not marked neither covariant nor contravariant (as it cannot be, it's not an interface), so that's why it doesn't work.