0

When I assign a Dictionary<int, HashSet<int>> to a IDictionary<int, IEnumerable<int>>, I get the following error:

Compilation error (line 27, col 9): Cannot implicitly convert type 'System.Collections.Generic.Dictionary>' to 'System.Collections.Generic.IDictionary>'. An explicit conversion exists (are you missing a cast?)

The error is quite clear. A cast is missing. Why do I need a cast here? Dictionary<T,U> implements IDictionary<T,U> and HashSet<T> implements IEnumerable<T>.

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{   
    public class A
    {
        public IDictionary<int, IEnumerable<int>> D { get; set; }
        public IEnumerable<int> H { get; set; }
    }

    public static void Main()
    {
        var hashSet = new HashSet<int>{1,2,1};
        var a = new A { H = hashSet };
        PrintCollection(a.H);

        var d = new Dictionary<int, HashSet<int>>{{ 3, hashSet  }};
        a.D = d; // error here
        PrintCollection(a.D.First().Value);
    }

    public static void PrintCollection(IEnumerable<int> collections)
    {
        foreach (var item in collections)
            Console.WriteLine(item);
    }
}

Try it Online!

aloisdg
  • 22,270
  • 6
  • 85
  • 105

2 Answers2

6

You can't. If you take a variable of type IDictionary<int, IEnumerable<int>> and try to add say an IList<int> as a value - which by the type of the variable, you should be able to do - then in your case that actually entails adding an invalid member to your Dictionary<int, HashSet<int>>. You can't cast this type because that would be using the type system to say something that isn't true - that any IEnumerable<int> can be added to the dictionary - it cannot.

Tom W
  • 5,108
  • 4
  • 30
  • 52
1

Variance in C# is opt-in only when safe to do so.

IEnumrable<out T> supports covariance but IDictionary<TKey, TValue> does not.

Notice the out keyword; that allows covariant assignment when the type is generally read-only.

Now imagine if IDictionary was covariant:

IDictionary<int, IEnumerable<int>> dict = new Dictionary<int, HashSet<int>>();
dict.Add(1, new List<int>()); // oh dear, added a list to a Dictionary<int, HashSet<int>>
Johnathan Barclay
  • 18,599
  • 1
  • 22
  • 35