Хотя можно найти практические обходные пути как у Стивена Клири
Func<T> CreateGetDefaultObject<T>() { return () => default(T); }
, где вы можете указать родовые значения напрямую, это довольно интересная проблема с теоретической точки зрения, которая не может быть решена текущей системой типов C #.
Тип, который, как вы его называете, сам по себе является общим , называется типом более высокого ранга .
Рассмотрим следующий пример (псевдо-C #):
Tuple<int[], string[]> Test(Func<?> f) {
return (f(1), f("Hello"));
}
В предложенной вами системе вызов может выглядеть так:
Test(x => new[] { x }); // Returns ({ 1 }, { "Hello" })
Но вопрос в том, как набрать функцию Test
и ее аргумент f
?
Очевидно, f
отображает каждый тип T
в массив T[]
этого типа. Так может быть?
Tuple<int[], string[]> Test<T>(Func<T, T[]> f) {
return (f(1), f("Hello"));
}
Но это не работает . Мы не можем параметризовать Test
с помощью любого конкретного T
, поскольку f
следует применять к всем типам T
. На данный момент система типов C # не может идти дальше.
Нам нужна была запись типа
Tuple<int[], string[]> Test(forall T : Func<T, T[]> f) {
return (f(1), f("Hello"));
}
В вашем случае вы можете набрать
forall T : Func<T> getDefaultValue = ...
Единственный язык, который я знаю, который поддерживает этот вид обобщения, это Haskell:
test :: (forall t . t -> [t]) -> ([Int], [String])
test f = (f 1, f "hello")
См. Эту запись в Haskellwiki по полиморфизму об этой forall
записи.