Initializing IDictionary <K, IEnumerable <V>>

I have a method with a signature

public void Foo(IDictionary<string, IEnumerable<string>> data)
{
}

and want to go through

private Dictionary<string, HashSet<string>> myInput = 
    new Dictionary<string, HashSet<string>>()
{
};      

Line

Foo(myInput);

gives a compiler error:

Argument 1: cannot convert from System.Collections.Generic.Dictionary<string,System.Collections.Generic.HashSet<string>>toSystem.Collections.Generic.IDictionary<string,System.Collections.Generic.IEnumerable<string>>

Dictionary<K,V>implements IDictionary<K,V>and HashSet<T>implements IEnumerable<T>.

  • Why can't the compiler perform the conversion?
  • How to create an instance of data that I can transfer to Foo?

Note

If I changed my signature to

public void Foo(IDictionary<string, HashSet<string>> data)

compilation succeeds. However, I do not need any knowledge that a particular type, for example HashSet<T>, is passed. Anyone IEnumerable<T>will do.

UPDATE

The following compilations:

public void Foo(IDictionary<string, IEnumerable<string>> data)
{
    List<string> item = new List<string>() { "foo", "bar", "baz" };
    data.Add("key", item);
    HashSet<string> item2 = new HashSet<string>() { "quu" };
    data.Add("key2", item2);
}

so clearly datacan take mixed-type values ​​that all implementIEnumerable<T>

+4
3

, , . - , .

, Foo , promises, :

var myInput = new Dictionary<string, HashSet<string>>();

// assuming a valid signature for `Foo`
Foo(myInput);

// according to the type of `myInput` the following MUST work
HashSet<string> item = myInput["foo"];
item.Add("baz");

, . , Foo , .

, , Foo:

public void Foo (IDictionary<string, IEnumerable<string>> data)
{
    List<string> item = new List<string>(){ "foo", "bar" };
    data.Add("foo", item);
}

List<string> IEnumerable<string>, , IEnumerable<string>, . : - Foo .

, , : , "foo", HashSet<string>, a List<string>. , HashSet<string> item = myInput["foo"] . ! , , Foo; Foo .

, , - , . Foo . , IDictionary , .

+4

@poke , .

, where :

public void Foo<T>(IDictionary<string, T> data)
    where T : IEnumerable<string>
{
}

Foo , IEnumerable<string>, . , , .

, :

public void Foo<T>(IDictionary<string, T> data)
    where T : ICollection<string>, new()
{
    var col = new T();
    col.Add("bar");

    data["col"] = col;
}

:

var a = new Dictionary<string, HashSet<string>>();
var b = new Dictionary<string, List<string>>();
var c = new Dictionary<string, LinkedList<string>>();

Foo(a);
Foo(b);
Foo(c);

. , bar.

, Dictionary. -. , , . Foo .

+1

According to my comment, here is a way to make your call work with a little LINQ help:

Foo(myInput.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.AsEnumerable()));
0
source

Source: https://habr.com/ru/post/1538500/


All Articles