Próbowałem ostatnio zrobić takie coś:
interface IWrapper<TItem> {
ICollection<TItem> Items {get;set;}
}
class MyWrapper : IWrapper<sting>{
public ICollection<string> Items{get;set;}
}
class Operator {
public TWrapper DoSomething<TWrapper, TItem>()
where TWrapper : IWrapper<TItem>
{
// ...
}
}
Następnie chciałem, żeby kompilator sam domyślił się drugiego argumentu generycznego, gdy wołam DoSomething
:
operator.DoSomething<Wrapper>();
zamiast
operator.DoSomething<Wrapper, string>();
Niestety, pierwsze opcja wywalała kompilację z komunikatem, że kompilator nie potrafi domyślić się typu tego drugiego argumentu generycznego. No ale - jak to? Skoro określam w where
, że TRequest
ma implementować interfejs IWrapper<TItem>
, a TItem
jest drugim argumentem, to chyba wiadomo, że np. dla TRequest = IWapper<int>
- TItem = int
?
A jednak - nie! Jak zwykle odpowiedź przychodzi ze Stack Overflow - tym razem sam Eric Lippert, który pracował onegdaj przy kompilatorze C# wyjaśnia, że:
A bunch of people have pointed out that C# does not make inferences based on constraints. That is correct, and relevant to the question. Inferences are made by examining arguments and their corresponding formal parameter types and that is the only source of inference information.
:(