Аргументы типа сигнатуры статического метода и частичное применение
В последнее время я изучаю функциональное программирование и хочу донести некоторые концепции до C#
Мир. Я пытаюсь составить функции для создания служб (или как бы вы их ни называли) вместо создания классов с инъекционными зависимостями.
Я придумал способ частично применить функцию (чтобы иметь тот же эффект, что и внедрение зависимостей) с двумя аргументами и одним возвращаемым аргументом, создав статический метод, подобный этому:
// this makes a func with a single arg from a func with two
static Func<T2, TResult> PartiallyApply<T1, T2, TResult>(
Func<T1,T2, TResult> f,
T1 t1)
{
// use given t1 argument to create a new function
Func<T2, TResult> map = t2 => f(t1, t2);
return map;
}
Это работает, однако я хотел бы передать ему статический метод, как этот:
static string MakeName(string a, string b) => a + " " + b;
Когда я пытаюсь подключить это, я получаю ошибку The type arguments for method 'Program.PartiallyApply<T1, T2, TResult>(Func<T1, T2, TResult>, T1)' cannot be inferred from the usage.
Но когда я добавляю шаг, создающий явное Func<string,string,string
который я указываю на метод, который он работает:
static void Main(string[] args)
{
var first = "John";
var last = "Doe";
var f1 = PartiallyApply(MakeName, first); // cannot be inferred from the usage
Func<string, string, string> make = MakeName; // map it to func
var f2 = PartiallyApply(make, first); // works
var name = f2(last);
Console.WriteLine(name);
Console.ReadKey();
}
Почему компилятор не может обработать аргументы типа при прямой передаче статического метода? Есть ли способ, где я мог бы использовать статические методы без необходимости явно отображать их в Func<>
с по существу одинаковыми (типовыми) аргументами?
ОБНОВЛЕНИЕ Чтение Functional programming in C#
от Enrico Buonanno
(настоятельно рекомендуется) дает еще один хороший вариант для решения этой проблемы. В 7.1.3
он дает несколько вариантов работы с Funcs
напрямую, вместо групп методов. Вы могли бы сделать свойство только геттер с Func
как это:
static Func<string, string, string> MakeName => (a,b) => a + " " + b;
1 ответ
Потому что, если у вас есть два метода с разными аргументами, компилятор не знает, используйте method1 или method2.
пример:
static string MakeName(string a, string b) => a + " " + b;
static string MakeName(int a, string b) => a + " " + b;
Как мог компилятор узнать, что вы имеете в виду? Метод1 или метод2? То, что у вас есть только один метод в группе методов, не означает, что так будет всегда. Добавление метода будет нарушено таким образом.
var f1 = PartiallyApply(MakeName, first);
Поэтому, если вы хотите решить эту проблему, вы должны установить общие аргументы в вызове метода:
var f1 = PartiallyApply<string, string, string>(MakeName, first);
var f2 = PartiallyApply<string, int, string>(MakeName, first);
Или вы можете получить все аргументы в вашем методе PartiallyApply:
static string MakeName(string a, string b) => a + " " + b;
static string MakeName(int a, string b) => a + " " + b;
// this makes a func with a single arg from a func with two
static Func<T2, TResult> PartiallyApply<T1, T2, TResult>(
Func<T1, T2, TResult> f,
T1 t1,
T2 t2)
{
// use given t1 argument to create a new function
Func<T2, TResult> map = result => f(t1, t2);
return map;
}
static void Main(string[] args)
{
var first = "John";
var last = "Doe";
var f1 = PartiallyApply(MakeName, first, last); //works now
var name = f1(last);
Console.WriteLine(name);
Func<string, string, string> make = MakeName; // map it to func
var f2 = PartiallyApply(make, first, last); // works
name = f2(last);
Console.WriteLine(name);
Console.ReadKey();
}