Кажется, что ответ «нет».
Когда вы звоните Transform
напрямую, вы должны указать параметр типа:
int i = Transform<int>("");
Так гипотетически, если вы могли бы пройти неполностью сконструированный обобщенную функцию, как вы хотите, вы должны указать введите параметры, а также:
void GeneralizedFunction(string aStringA, string aStringB, Func<string, T> aAction)
{
A result1 = aAction<A>(aStringA);
B result2 = aAction<B>(aStringB);
// Do something with A and B here
}
так что, мне кажется, что вы могли бы гипотетически сделать это, если C# был синтаксис, как это.
Но какой прецедент? Помимо преобразования строк в значение по умолчанию для произвольного типа, я не вижу большого смысла для этого. Как вы могли бы определить функцию, которая обеспечивала бы значимый результат в любом из двух разных типов, используя ту же последовательность утверждений?
EDIT
Анализ, почему это не представляется возможным:
При использовании лямбда-выражения в коде, он компилируется в любой делегат или дерева выражений; в этом случае это делегат. Вы не можете иметь экземпляр «открытого» типа общего типа; другими словами, для создания объекта из общего типа необходимо указать все параметры типа.Другими словами, нет возможности иметь экземпляр делегата без предоставления аргументов для всех его параметров типа.
Одна из полезных функций компилятора C# - это неявные преобразования групп методов, где имя метода («группа методов») может быть неявно преобразовано в тип делегата, представляющий одну из перегрузок этого метода. Точно так же компилятор неявно преобразует лямбда-выражение в тип делегата. В обоих случаях компилятор испускает код для создания экземпляра типа делегата (в этом случае передать его функции). Но экземпляр этого типа делегата по-прежнему должен иметь аргумент типа для каждого из его параметров типа.
Чтобы передать общую функцию как обобщенная функция, кажется, компилятор должен был бы быть в состоянии пройти группу метод или лямбда-выражения методу без преобразования, поэтому aAction
параметр каким-то образом будет иметь тип «группа методов» или «лямбда-выражение». Затем неявное преобразование в тип делегата может произойти на сайтах вызовов A result1 = aAction<A>(aStringA);
и B result2 = aAction<B>(aStringB);
. Конечно, на данный момент мы хорошо во вселенной противопоказаний и гипотез.
Решение, которое я придумал за обедом было это, предполагая, что функция Deserialize<T>
, которая принимает строку, содержащую сериализованные данные и возвращает объект типа T
:
void GeneralizedFunction<T>(string aStringA, string aStringB, Func<T, string> stringGetter)
{
A result1 = Deserialize<A>(stringGetter(aStringA));
B result2 = Deserialize<B>(stringGetter(aStringB));
}
void Example(string serializedA, string serializedB, string pathToA, string pathToB, FileInfo a, FileInfo b)
{
GeneralizedFunction(serializedA, serializedB, s => s);
GeneralizedFunction(pathToA, pathToB, File.ReadAllText);
GeneralizedFunction(a, b, fi => File.ReadAllText(fi.FullName));
}
Что это вы хотите сделать именно? так как вы не хотите предоставлять GeneralizedFunction информацию о типе в отношении функции Transform, почему бы не принять func снова, взяв строку и возвращая объект (каждый из которых знает, что все есть *) – Polity
Дело в том, что «Сделайте что-то с A и B "скрывает проблематичную часть. Всегда ли А и В будут конкретными типами? Тогда вам не нужны дженерики. Являются ли они произвольными (возможно, с ограничениями) типами? Тогда «Обобщенная функция» должна быть общей в них. – AakashM
A и B - конкретные типы, но Transform - это общая функция. – Max