Search code examples
c#collectionsinterfacedecoupling

C# Passing a collection as a collection of interfaces


I have simplified and reproduced my problem in the code below. The error that I am receiving is: Argument 1: cannot convert from 'System.Collections.ObjectModel.Collection' to 'System.Collections.ObjectModel.Collection

Some background for the design decisions that led to this issue: I have created a web service for dealing with "IFruit", but due to the nature of SOAP and endpoint bindings as I understand them I have created methods with explicit implementations of IFruit. On the business layer, creating a separate method for each specific implementation of fruit would firstly cause a lot of duplicate code, and secondly couple the business and service layer tightly enough that accepting new IFruit types in the web service later would also require changing my code in the business layer (adding another copy of redundant code). This design is one I have successfully implemented using Java in the past, but C# interfaces seem to be just different enough to throw me. Please advise.

public interface IFruit{
    public string TakeBite();
}

public Apple : IFruit{
    public string TakeBite(){
        return "tasty bite of apple";
    }
}

public void EatFruit(Collection<IFruit> fruits){
    foreach(var fruit in fruits){
        Console.WriteLine(fruit.TakeBite());
    }
}

public void EatApples(Collection<Apple> apples){
    this.EatFruit(apples);
}

Solution

  • Try changing your EatFruit method to accept IEnumerable<IFruit>

    public void EatFruit(IEnumerable<IFruit> fruits)
    {
        foreach (var fruit in fruits)
        {
            Console.WriteLine(fruit.TakeBite());
        }
    }
    

    The interface IEnumerable<out T> supports covariance since it is marked with the out modifier. Collection<T> is not marked with such a modifier.