Объяснение Func

89

Мне было интересно, может ли кто-нибудь объяснить, что это Func<int, string>такое и как это используется, с некоторыми ясными примерами.

zОбзор
источник

Ответы:

145

Вы в целом знакомы с делегатами? У меня есть страница о делегатах и ​​мероприятиях, которая может помочь, если нет, хотя она больше ориентирована на объяснение различий между ними.

Func<T, TResult>является просто универсальным делегатом - выясните, что он означает в любой конкретной ситуации, заменив параметры типа ( Tи TResult) соответствующими аргументами типа ( intи string) в объявлении. Я также переименовал его, чтобы избежать путаницы:

string ExpandedFunc(int x)

Другими словами, Func<int, string>это делегат, который представляет функцию, принимающую intаргумент и возвращающую string.

Func<T, TResult>часто используется в LINQ как для проекций, так и для предикатов (в последнем случае TResultвсегда bool). Например, вы можете использовать a Func<int, string>для проецирования последовательности целых чисел в последовательность строк. Лямбда-выражения обычно используются в LINQ для создания соответствующих делегатов:

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);
}

Результат:

Value=3
Value=7
Value=10
Джон Скит
источник
3
«Другими словами, это делегат, который представляет функцию, принимающую аргумент типа int и возвращающую строку». Чтобы избежать путаницы для других, я поясню, что вы говорите здесь о Func <int, string>, а не о Func <T, TResult>. Это очевидно, если вы понимаете общие типы и делегаты, но для тех, кто не понимает, это Func <int, string>, который kan делегирует функцию, которая принимает аргумент int и возвращает строку.
Настоящий napster
Поясню, когда вернусь к ПК позже.
Джон Скит
2
Я думаю, что на самом деле это не так ясно, как описание и пример MSDN. Я также думаю, что вам следует добавить информацию о том, как последний параметр типа является возвращаемым типом, поясняя, что Func <int, int, string> возвращает строку и принимает 2 целых числа. Это помогает прояснить ситуацию. Ничего личного - я просто не думал, что это достаточно ясно.
TheSoftwareJedi
11
Итак, вы собираетесь понижать каждый ответ, который, по вашему мнению, не так полезен, как ваш любимый? Как вы думаете, этот ответ бесполезен ? Вы думаете, что, возможно, неплохо было бы иметь более одного взгляда на вещи?
Джон Скит
8
@TheSoftwareJedi: Нет, конечно, нет причин принимать ваш отрицательный голос лично - тот факт, что вы сделали отрицательный голос по личным причинам в субботу, а затем случайно зашли в эту ветку после того, как мы долго обсуждали по электронной почте вопрос о правильном поведении это совершенно случайно, не так ли?
Джон Скит
40

A Func<int, string>ест целые числа и возвращает строки. Итак, что ест целые числа и возвращает строки? Как насчет этого ...

public string IntAsString( int i )
{
  return i.ToString();
}

Я только что придумал функцию, которая ест целые числа и возвращает строки. Как мне это использовать?

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"

Я знаю, не очень сексуально, но это простая идея, на которой основано множество трюков. Теперь давайте воспользуемся 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

Вместо вызова IntAsString для каждого члена я создал ссылку на него с именем fnc (эти ссылки на методы называются делегатами ) и использовал ее вместо этого. (Помните, что fnc ест целые числа и возвращает строки).

Этот пример не очень привлекателен, но множество умных вещей, которые вы увидите, основаны на простой идее функций, делегатов и методов расширения .

Один из лучших грунтовок на этом материале я видел здесь . У него гораздо больше реальных примеров. :)

JP Alioto
источник
@Therealnapster, мне тоже нравится, но твое имя мне нравится больше.
BKSpurgeon
28

Это делегат, который принимает единицу intв качестве параметра и возвращает значение типа string.

Вот пример его использования:

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();
    }
}
Эндрю Хэйр
источник
3
Спасибо, Андрей. Вы хотели написать func (1) вместо bar (1)?
zSynopsis
1

Func<int, string>принимает параметр значения типа int и возвращает строковое значение. Вот пример, когда дополнительный метод поддержки не нужен.

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);

ПРИМЕЧАНИЕ. Последний тип объекта в Func (то есть «строка» в этом примере) - это тип, возвращаемый функцией (то есть не ограничивается примитивами, но любым объектом). Следовательно, Func<int, bool, float>принимает параметры значений типа int и bool и возвращает значение с плавающей запятой.

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

jts
источник