0

I have written the following method:

    public static Dictionary<K, V> ListToDictionary<E, K, V>(
       List<E> list, Func<E, K> keyProvider, Func<E, V> valueProvider)
    {
        Dictionary<K, V> dictionary = new Dictionary<K, V>();
        foreach (E e in list)
        {
            K key = keyProvider(e);
            V value = valueProvider(e);
            dictionary.Add(key, value);
        }
        return dictionary;
    }

This method takes in a list and transforms it into a dictionary using the given functions to extract keys and values from the list elements. Now, to shorten things I have the following interface:

public interface IKeyValueProvider<K, V>
{
    K GetKey();
    V GetValue();
}

And an overload of the method mentioned above, looking like this:

    public static Dictionary<K, V> ListToDictionary<E, K, V>(List<E> list) where E : IKeyValueProvider<K, V>
    {
        return ListToDictionary(list, x => x.GetKey(), x => x.GetValue());
    }

I hoped that I could use this construction as follows:

Utils.ListToDictionary(someList)

Where someList is a List and E is a type (in my case, a struct) implementing IKeyValueProvider with concrete type parameters for K and V. But this does not seem to be possible since I get the error

The type arguments for method 'Dictionary Roadster.Other.Utils.ListToDictionary(List)' cannot be inferred from the usage.

Why is C# not able to infer the type arguments in such a scenario? Am I missing something obvious, which is the reason why they are not unique in this case, or is this simply not supported?

Edit: Sorry for the missing transparency of my "does not work" claim. Here is an example of how I try to use that functionality. I am a C# beginner, so maybe I am doing things fundamentally wrong. So here is the example:

The struct, implementing IKeyValueProvider:

    public struct A : IKeyValueProvider<string, string>
    {
        public string s1;
        public string s2;

        public string GetKey() => s1;
        public string GetValue() => s2;
    }

Usage of the method:

    public void TestMethod()
    {
        A a1 = new A { s1 = "test", s2 = "banana" };
        A a2 = new A { s1 = "serh", s2 = "weiougnw" };
        List<A> aList = new List<A> { a1, a2 };
        Dictionary<string, string> test = Utils.ListToDictionary(aList);
    }

As I am assigning the result to a Dictionary explicitly, I would expect the arguments to be inferable here.

T_01
  • 1,256
  • 3
  • 16
  • 35
  • Did you assign `Utils.ListToDictionary(someList)` to a variable? What is type of items in `someList` and how does them implement `IKeyValueProvider`? There are a lot of hidden things in your question – Pavel Anikhouski May 24 '20 at 14:46
  • 1
    Sorry for my somewhat blackboxy question. I added a concrete example of what I am trying to do. – T_01 May 24 '20 at 14:59
  • You can refer to this question [Why doesn't C# infer my generic types?](https://stackoverflow.com/questions/8511066/why-doesnt-c-sharp-infer-my-generic-types) for details. I'm not 100% sure, but compiler can inter only generic types, used in method arguments, not in the return value. It seems to be your case, because `K` and `V` used only in return type `Dictionary`. Partial inference isn't supported (yet) – Pavel Anikhouski May 24 '20 at 15:10
  • Okay, I guess this is the case then. Thank you – T_01 May 24 '20 at 15:13
  • For the same reason the first overload of `ListToDictionary` method with `Func` will work with inferred type parameters, because all of them are used in method arguments – Pavel Anikhouski May 24 '20 at 15:14

0 Answers0