Jak napisać w C# metody, które traktują lambdy jako parametry
Jeśli dopiero zaczynasz z C# albo ASP.NET Core, to pomimo, że metody, które używają wyrażeń lambda jako parametrów nie są dla Ciebie obce, możesz nie wiedzieć jak je samemu napisać.
Weźmy na przykład metodę Configure z aplikacji ASP.NET Core:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Zauważ, w jaki sposób wyrażenie lambda jest przekazane jako argument w metodzie UseEndpoints()
. Jak więc taką metodę napisać?
Wyrażenie lambda vs. delegaty
Zbadajmy najpierw różnice między nimi.
Delegat - zmienna będąca typem referencyjnym, która przechowuje referencję do danej metody.
Wyrażenie lambda - w C# jest używane jako anonimowa funkcja, z tą różnicą, że w lambdach nie trzeba określać typu wartości, który wprowadzasz, przez co jest ono bardziej elastyczne w użyciu.
Każde wyrażenie lambda może być przekonwertowane na delegat. Typ delegata, na który dane wyrażenie może być przekonwertowane, jest definiowany przez typy przyjmowanych parametrów i zwracanych wartości.
Jeśli wyrażenie lambda nie zwraca wartości, to można je przekonwertować na jeden z delegatów typu Action.
W innym przypadku, możliwe jest przekonwerowanie ich na jeden z delegatów typu Func. Na przykład, wyrażenie lambda, które posiada dwa parametry i nie zwraca żadnej wartości, może być przekonwertowane na delegat Action<T1,T2>.
Wyrażenie lambda, które ma tylko jeden parametr i zwraca wartość może zostać przekonwertowane na delegat Func<T,TResult>.
Oznacza to tyle, że podczas pisania metody, która traktuje wyrażenie lambda jako parametr, musimy go określić jako odpowiedni delegat.
Przykład w kodzie
Oto, co zrobię w poniższym przykładzie:
- Stworzę klasę Model.
- Stworzę metodę, która wygeneruje losowe dane. Metoda ta przyjmie wyrażenie lambda jako parametr, który zdefiniuje, jak te dane będą generowane.
- Stworzę kolejną metodę, która zmieni właściwości klasy Model. Metoda ta również przyjmie wyrażenie lambda jako parametr, który zdefiniuje sposób w jaki właściwości klasy zostaną zmienione.
Oto jak to wygląda:
Stworzenie klasy Model
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Stworzenie metod
public static class PersonExtensions
{
public static void GenerateRandomName(this Person person, Func<Person> action)
{
var randomPerson = action();
person.FirstName = randomPerson.FirstName;
person.LastName = randomPerson.LastName;
}
public static void Mutate(this Person person, Func<string, string> action)
{
person.FirstName = action(person.FirstName);
person.LastName = action(person.LastName);
}
}
Wyrażenie lambda jako parametr
Jesteśmy teraz gotowi do przeprowadzenia testu.
Poniżej znajduje się aplikacja konsolowa, która używa metod zdefiniowanych powyżej.
using Faker;
using System;
using Workspace.Extensions;
namespace Workspace
{
public class Program
{
private static void Main(string[] args)
{
var randomPerson = new Person();
randomPerson.GenerateRandomName(() =>
{
return new Person()
{
FirstName = Name.First(),
LastName = Name.Last()
};
});
Console.WriteLine($"{randomPerson.FirstName} {randomPerson.LastName}"); // Output: Rico Wiegand
randomPerson.Mutate(x => x.ToUpper());
Console.WriteLine($"{randomPerson.FirstName} {randomPerson.LastName}"); // Output: RICO WIEGAND
}
}
}