Zastanawiałem się, czy ktoś mógłby wyjaśnić, co to Func<int, string>
jest i jak jest używane, z jasnymi przykładami.
Odpowiedzi:
Czy ogólnie znasz delegatów? Mam stronę o delegatach i wydarzeniach, która może pomóc, jeśli nie, chociaż jest bardziej nastawiona na wyjaśnienie różnic między nimi.
Func<T, TResult>
jest tylko delegatem ogólnym - dowiedz się, co to oznacza w dowolnej konkretnej sytuacji, zastępując parametry typu ( T
i TResult
) odpowiednimi argumentami typu ( int
i string
) w deklaracji. Zmieniłem też jego nazwę, aby uniknąć nieporozumień:
string ExpandedFunc(int x)
Innymi słowy, Func<int, string>
jest delegatem, który reprezentuje funkcję pobierającą int
argument i zwracającą string
.
Func<T, TResult>
jest często używany w LINQ, zarówno dla prognoz, jak i predykatów (w tym drugim przypadku TResult
jest zawsze bool
). Na przykład można użyć a, Func<int, string>
aby zaprojektować sekwencję liczb całkowitych na sekwencję ciągów. Wyrażenia lambda są zwykle używane w LINQ do tworzenia odpowiednich delegatów:
Func<int, string> projection = x => "Value=" + x;
int[] values = { 3, 7, 10 };
var strings = values.Select(projection);
foreach (string s in strings)
{
Console.WriteLine(s);
}
Wynik:
Value=3
Value=7
Value=10
A Func<int, string>
zjada ints i zwraca stringi. Więc co zjada int i zwraca ciągi? Co powiesz na to ...
public string IntAsString( int i )
{
return i.ToString();
}
Tam właśnie stworzyłem funkcję, która zjada ints i zwraca ciągi. Jak bym tego użył?
var lst = new List<int>() { 1, 2, 3, 4, 5 };
string str = String.Empty;
foreach( int i in lst )
{
str += IntAsString(i);
}
// str will be "12345"
Wiem, że niezbyt seksowne, ale na tym polega prosta idea, na której opiera się wiele sztuczek. Teraz użyjmy zamiast tego Func.
Func<int, string> fnc = IntAsString;
foreach (int i in lst)
{
str += fnc(i);
}
// str will be "1234512345" assuming we have same str as before
Zamiast wywoływać IntAsString na każdym elemencie członkowskim, utworzyłem odwołanie do niego o nazwie fnc (te odwołania do metod nazywane są delegatami ) i zamiast tego użyłem tego. (Pamiętaj, że fnc zjada wartości int i zwraca ciągi znaków).
Ten przykład nie jest zbyt seksowny, ale mnóstwo sprytnych rzeczy, które zobaczysz, opiera się na prostej idei funkcji, delegatów i metod rozszerzających .
Jeden z najlepszych podkładów na ten temat, jaki widziałem, jest tutaj . Ma o wiele więcej prawdziwych przykładów. :)
Jest to delegat, który przyjmuje je int
jako parametr i zwraca wartość typu string
.
Oto przykład jego użycia:
using System;
class Program
{
static void Main()
{
Func<Int32, String> func = bar;
// now I have a delegate which
// I can invoke or pass to other
// methods.
func(1);
}
static String bar(Int32 value)
{
return value.ToString();
}
}
Func<int, string>
akceptuje parametr wartości int i zwraca wartość ciągu. Oto przykład, w którym dodatkowa metoda wspomagająca nie jest konieczna.
Func<int, string> GetDogMessage = dogAge =>
{
if (dogAge < 3) return "You have a puppy!";
if (dogAge < 7) return "Strong adult dog!";
return "Age is catching up with the dog!";
};
string youngDogMessage = GetDogMessage(2);
UWAGA: Ostatnim typem obiektu w Func (tj. „String” w tym przykładzie) jest typ zwracany przez funkcje (tj. Nie jest ograniczony do prymitywów, ale dowolnego obiektu). Dlatego Func<int, bool, float>
akceptuje parametry wartości typu int i bool i zwraca wartość zmiennoprzecinkową.
Func<int, bool, float> WorthlessFunc = (intValue, boolValue) =>
{
if(intValue > 100 && boolValue) return 100;
return 1;
};
float willReturn1 = WorthlessFunc(21, false);
float willReturn100 = WorthlessFunc(1000, true);
HTH