Несколько слов, что можно сказать о Func <>
Вопрос
Я увинул Func <> Насколько сейчас сейчас, и мне удается избежать его (на данный момент). Но, теперь похоже, я не могу увернуться навсегда. Например, я попробовал Dynamic Linq, но почти все было с точки зрения функции func <>. Я пробовал одну из моих книг (C # 2008 / Deitel & Deitel), а также MSDN, но я еще не получаю его. Все они прыгают прямо в тему.
- Что можно сказать (в нескольких словах) о функциях <>
- Могу ли я получить некоторые ссылки в Интернете, которые могут заставить меня начаться по этому вопросу?
Спасибо за помощь
Решение
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);
И вы получите тот же результат.