I've been coding some exception- and type-safe retrieval-extensions for various generic collections when I stumbled acrross - at least for my understanding - odd behaviour of the c# compiler.
Let's say we have:
var sgDict = new Dictionary<string, object> { ["a"] = "x", ["b"] = 6 };
These two extensions signatures work fine (their ier implementations don't matter now):
(1) public static T2 safeGet<T1, T2>(this IDictionary<T1, T2> dict, T1 key);
(2) public static T safeGet<T1, T>(this IDictionary<string, T1> dict);
Using these, I can write
(1) var sgVal = sgDict.safeGet("b"); // ok, object { 6 }
(2) var sgVal = sgDict.safeGet<int>("b"); // ok, int { 6 }
But using this signature, a "combination" of (1)+(2):
(3) public static T1 safeGet<T1, T2, T3>(this Dictionary<T2, T3> dict, T2 key);
I caot write
(3) var sgVal = sgDict.safeGet<int>("b"); // error: "safeGet" not defined for Dictionary<string, object>
I even tried "reordering" T1-T3. I would have to write instead:
(3) var sgVal = sgDict.safeGet<int, string, object>("b"); // ok, int { 6 }
I wonder, why can the compiler correctly infer T1,T2 for (1) and T1 for (2), but not T2,T3 for (3)?
