Аргументы типа сигнатуры статического метода и частичное применение - PullRequest
0 голосов
/ 01 июня 2018

В последнее время я изучаю функциональное программирование и хочу привнести некоторые концепции в мой 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 Ответ

0 голосов
/ 10 июня 2018

Потому что, если у вас есть два метода с разными аргументами, компилятор не знает, используйте 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();
    }
...