I was reading C# in depth , got confused in 2-phase type inference rule explained by dear author.
Consider the code :
static void PrintConvertedValue<TInput,TOutput> (TInput input, Converter<TInput,TOutput> converter)
{ Console.WriteLine(converter(input)); }
...
PrintConvertedValue("I'm a string", x => x.Length);
after which he explains the process of inference using 2-phase inference algo.
1.Phase 1 begins.
2.The first parameter is of type TInput, and the first argument is of type string. We infer that there must be an implicit conversion from
string to TInput.3.The second parameter is of type Converter, and the second argument is an implicitly typed lambda expression. No inference
is performed—we don’t have enough information.4.Phase 2 begins.
5.
TInputdoesn’t depend on any unfixed type parameters, so it’s fixed to string.6.The second argument now has a fixed input type, but an unfixed output type. We can consider it to be
(string x) => x.Lengthand infer
the return type as int. Therefore an implicit conversion must take
place from int toTOutput.7.Phase 2 repeats.
8.
TOutputdoesn’t depend on anything unfixed, so it’s fixed to int. 9There are now no unfixed type parameters, so inference succeeds
I am very confused with step 2 and step 5. In step 2 how can compiler make inference like that ? I mean how in world conversion comes in to the scene? Conversion happens BTW types not BTW type parameters and types, isn’t it?.
And step 5 completely eluded me, can anyone present me simplified example where a type parameter can depend on other type parameter please with explanation what author is trying to imply?
I dared to lurk in to C# specification but seems intelligent peoples made it for very similar intelligent peoples, not for monkeys like me 🙂
Conversion happens for values, and the fact that we’re able to call the method using a string value as the argument for a parameter of type
TInputmeans that there must be a conversion fromstringtoTInput. IfTInputwere inferred to beint, then we’d be calling a method requiring anint, but giving it astring– which is clearly not valid.Note that for a simpler example, just change it to:
called with:
There has to be a conversion from
stringtoTin order for the call to be valid, and as there’s no other information aboutT, we infer thatTis simplystring.In a slightly more complicated example, you could have:
Here, we infer that:
stringtoTobjecttoT… so we infer that
Tisobject.As for type parameter dependencies, from section 7.5.2.5 of the C# 5 specification:
So for example:
And:
Here
T2depends onT1– once we’ve inferredT1, we can inferT2.