Объяснение Func


89

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

Ответы:


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 ест целые числа и возвращает строки).

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

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


@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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.