Несколько слов, что можно сказать о Func <>

StackOverflow https://stackoverflow.com/questions/2661669

  •  27-09-2019
  •  | 
  •  

Вопрос

Я увинул Func <> Насколько сейчас сейчас, и мне удается избежать его (на данный момент). Но, теперь похоже, я не могу увернуться навсегда. Например, я попробовал Dynamic Linq, но почти все было с точки зрения функции func <>. Я пробовал одну из моих книг (C # 2008 / Deitel & Deitel), а также MSDN, но я еще не получаю его. Все они прыгают прямо в тему.

  1. Что можно сказать (в нескольких словах) о функциях <>
  2. Могу ли я получить некоторые ссылки в Интернете, которые могут заставить меня начаться по этому вопросу?

Спасибо за помощь

Это было полезно?

Решение

Func<> Это общий делегат - просто очень удобно использовать, потому что вам не нужно создавать свой собственный делегат для каждого комбинации типа аргумента / возврата.
Раньше вам пришлось написать что-то вроде:

public delegate long MyDelegate( int number );

public void Method( IEnumerable<int> list, MyDelegate myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

Вы должны были опубликовать свой делегат, чтобы пользователь мог правильно позвонить вашему методу. Особенно, когда вам нужен куча разных делегатов, вы закончили публиковать один для каждого списка аргументов и типа возврата.
С участием Func<> Вы просто пишете:

public void Method( IEnumerable<int> list, Func<int, long> myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

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

Конечно, вы можете использовать более длинные списки параметров: Func<int, int, bool, long> все еще вернет длинная Значение, пока требуется два ints. и а бол стоимость. Если вы хотите, чтобы делегата без возврата, вам придется использовать Action<>, который будет иметь пустота как тип возврата.

РЕДАКТИРОВАТЬ (по запросу): Как вызвать метод в моем примере:

Для вызывающего абонента нет разницы между решением с MyDelegate или Func<>. Отказ В обоих случаях у него есть три варианта, чтобы вызвать метод:

Используя нотацию лямбда (требуется C # 3.0, возможно, лучшее решение для коротких методов):

Method( myList, i => i * i );

Используя анонимный метод (требуется C # 2.0):

Method( myList, delegate( int i )
{
    return i * i;
} );

Или используя реальный метод в качестве аргумента:

Method( myList, Square );

private static long Square( int number )
{
    return number * number;
}

Другие советы

Func<...> это семья типов делегатов, которые возвращают некоторое значение и возьмите некоторое количество аргументов; Например:

  • Func<int,bool> это просто то, что принимает int и возвращает лол (возвращение всегда в конце); Например, предикат:

    int[] data = {1,2,3,4,5};
    var odd = data.Where(i => i % 2 == 0);
    
  • Func<string> это метод, который возвращает строку, например, () => "hello world";.

  • Func<DateDtime, TimeSpan, DateTime> может быть что-то вроде (when,howLong) => when + howLong;

Точно так же есть Action<...> что делает то же самое, но без возврата типа.

Там нет ничего магии о Func<...> - Это просто более простым способом выражения делегатов, в то время как A: Использование универсальных (полезных для LINQ) или B: не требует, чтобы вы посмотреть, что аргументы; Если тип делегата что-то неясное (PipeStreamImpersonationWorker Например) может быть трудно знать, что нужно; Если это было выражено как сопоставимое Action Было бы ясно, что не требуется никаких параметров и возврата void.

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

interface IFuncIntString
{
    string Invoke(int x);
}

То есть делегат является объектом, который реализует этот интерфейс. Он имеет один метод под названием Invoke, который принимает int и возвращает строку.

Теперь добавьте к этому функцию, которую вы можете опустить «вызвать» по вызову, и вы получили себя делегатом.

Func<int> (Например) - это тип (так, как string это тип). Таким образом, вы используете его, чтобы объявить переменные, поля, параметры и так далее.

Он представляет собой вычисление, которое можно сделать всякий раз, когда вы спрашиваете его ответа:

Func<int> f = () => DateTime.Now.Second;

// elsewhere...

Console.WriteLine( f() );

Обратите внимание, как вы можете назвать это так же, как метод. Есть много перегруженных версий Func поддерживать разные номера параметров. Аргумент последнего типа - это тип возврата.

Func<int, string> quoteInt = n => "\"" + n + "\"";

Console.WriteLine( quoteInt(3) );

Func это тип делегата. Вы можете объявить свой собственный, но это будет проще в использовании Func. Отказ Где вы хотите вернуться void, использовать Action вместо Func. Отказ Вам нужно только объявить пользовательские делегаты, если вам нужно out или ref Параметры.

При назначении лямбда на Func, вы можете обратиться к локальным переменным. Это чрезвычайно мощно; это означает, что Func больше, чем просто код; У него есть данные. Таким образом, это как объект с одним методом (который технически это - метод называется Invoke И компилятор неявно вызывает этот метод для вас, когда вы называете делегатом).

Синтаксис () => Может быть размещен перед любого выражения, чтобы сказать «Не делай этого сейчас, задерживайте его до позже». Это позволяет инициализировать делегат, захватывающий задержку вычисления. А затем синтаксис () Можно разместить после того, как делегат на самом деле вызвать вычисление. Так суффикс () является добрым противоположностью префикса () =>.

Вы можете начать с 101 образцы LINQ.

Вкратце, Func<> Это делегат, в котором параметр последнего типа - это тип возврата.

Так, Func<int,bool> это делегат, который принимает int параметр и возвращает bool.

FUNC <..., T> делегат. где t - возвратный тип, и все остальные - входные параметры.

Если вы когда-либо использовали => Оператор в C #, и вы, вероятно, у вас уже использовали функциональные функции. Вы просто не были четко объявлены их.

Итак, если вы напишите заявление, как

var peopleWhoLikeBlue = people.Where(person => person.FavoriteColor == "Blue");

Вы проходите Func<Person, bool> в метод где ().

Если вы хотите быть Wordy, вы можете переписать это заявление, подобное это:

Func<Person, bool> favoriteColorIsBlue = person => person.FavoriteColor == "Blue";
var peopleWhoLikeBlue = people.Where(favoriteColorIsBlue);

И вы получите тот же результат.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top