Search code examples
c#linqgenericsinterfaceextension-methods

Error CS1061 when calling LINQ-extension on class implementing additional IEnumerable<>


I need to implement IEnumerable<KeyValuePair<int,IEnumerable<KeyValuePair<DateTime,double>>>> on a class that already derives from Dictionary<int,Dictionary<DateTime,double>> Unfortunately, the compiler gets confused when I try to access LINQ extensions like Any() and returns a CS1061:

public interface MyInterface
    : IEnumerable<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>>
{            
}

public class MyClass : Dictionary<int,Dictionary<DateTime, double>>, MyInterface            
{            
    //setting GetEnumerator() to public yields an CS0106
    IEnumerator<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>> 
        IEnumerable<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>>.GetEnumerator()
    {
        yield break;
    }

    static public void Foo(IEnumerable<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>> data)
    {
        //processing data...
    }            

    static void Demo()
    { 
        var mc = new MyClass();
        //stops working if MyInterface is implemented:
        mc.Any();//CS1061
        Foo(mc);
    }

    //Workaround for specific LINQ-extensions:
    //public bool Any() => this.Any();
}

At the end of the day, the class is used as parameter in methods like Foo(...) which is required to be more general than Dictionary.

How can we use LINQ on MyClass while also implementing MyInterface? (providing another approach to pass MyClass to Foo would also be helpfull, however it would not be the answer to the question).

the answer on a very similar question (LINQ gets confused when implementing IEnumerable<T> twice - Case 2) does not satisfy the requirements. Since implementing MyInterface is required, I would need to wrap the baseclass and redirect all used Dictionary-methods - I would be happy to have a more elegant solution.


Solution

  • Because your class implementes:

    1. IEnumerable<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>>
    2. IEnumerable<KeyValuePair<int, Dictionary<DateTime, double>>>

    The compiler cannot infer which Any method you want to call, it needs you to help it make decisions, for instance, you want to call Any on the first interface:

    mc.Any<KeyValuePair<int, IEnumerable<KeyValuePair<DateTime, double>>>>();