Разница между Func & lt; объектом, объектом, bool & gt; и метод возвращает тип типа bool и принимает два параметра объекта типа [duplicate]

select * from yourtable
group by id
having rev=max(rev);
83
задан CharithJ 16 July 2015 в 04:30
поделиться

6 ответов

Func<T> является предопределенным типом делегата для метода, который возвращает некоторое значение типа T.

Другими словами, вы можете использовать этот тип для ссылки на метод, который возвращает некоторое значение T. Например,

public static string GetMessage() { return "Hello world"; }

можно ссылаться так, как это

Func<string> f = GetMessage;
61
ответ дан Brian Rasmussen 4 September 2018 в 08:37
поделиться

Подумайте об этом как заполнитель. Это может быть весьма полезно, если у вас есть код, который следует за определенным шаблоном, но не должен быть привязан к какой-либо конкретной функции.

Например, рассмотрите метод расширения Enumerable.Select.

  • pattern : для каждого элемента в последовательности, выберите некоторое значение из этого элемента (например, свойство) и создайте новую последовательность, состоящую из этих значений.
  • placeholder : некоторая функция выбора, которая фактически получает значения для последовательности, описанной выше.

Этот метод принимает вместо Func<T, TResult> любую конкретную функцию. Это позволяет использовать его в в любом контексте , где применяется вышеприведенный шаблон.

Так, например, скажем, у меня есть List<Person>, и я хочу просто имя каждого человека в список. Я могу это сделать:

var names = people.Select(p => p.Name);

Или сказать, что я хочу возраст каждого человека:

var ages = people.Select(p => p.Age);

Сразу видно, как я был способен использовать тот же код, представляющий шаблон Select) с двумя различными функциями (p => p.Name и p => p.Age) .

Альтернативой было бы написать другую версию Select каждый раз, когда вы хотели бы сканировать последовательность для другого значения. Поэтому для достижения такого же эффекта, как и выше, мне понадобится:

// Presumably, the code inside these two methods would look almost identical;
// the only difference would be the part that actually selects a value
// based on a Person.
var names = GetPersonNames(people);
var ages = GetPersonAges(people);

Когда делегат выступает в качестве заполнителя, я освобождаюсь от необходимости повторять одну и ту же модель снова и снова в таких случаях.

73
ответ дан Dan Tao 4 September 2018 в 08:37
поделиться

Func<T1, T2, ..., Tn, Tr> представляет собой функцию, которая принимает (T1, T2, ..., Tn) аргументы и возвращает Tr.

Например, если у вас есть функция:

double sqr(double x) { return x * x; }

Вы можете сохранить его как какую-то функцию-переменную:

Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;

И затем используйте точно так же, как вы бы использовали sqr:

f1(2);
Console.WriteLine(f2(f1(4)));

и т. д.

Помните, что это делегат, поскольку более подробная информация относится к документации.

53
ответ дан Grozz 4 September 2018 в 08:37
поделиться

Я нахожу Func<T> очень полезным, когда создаю компонент, который нужно персонализировать «на лету».

Возьмем этот очень простой пример: компонент PrintListToConsole<T>.

Очень простой объект, который печатает этот список объектов на консоли. Вы хотите, чтобы разработчик, который использует его, персонализировал вывод.

Например, вы хотите дать ему определение определенного типа номера и т. Д.

Без Func

g7]

Во-первых, вам нужно создать интерфейс для класса, который берет ввод и выводит строку для печати на консоль.

interface PrintListConsoleRender<T> {
  String Render(T input);
}

Затем вам нужно создать класс PrintListToConsole<T> который принимает ранее созданный интерфейс и использует его по каждому элементу списка.

class PrintListToConsole<T> {

    private PrintListConsoleRender<T> _renderer;

    public void SetRenderer(PrintListConsoleRender<T> r) {
        // this is the point where I can personalize the render mechanism
        _renderer = r;
    }

    public void PrintToConsole(List<T> list) {
        foreach (var item in list) {
            Console.Write(_renderer.Render(item));
        }
    }   
}

Разработчик, которому необходимо использовать ваш компонент, должен:

  1. реализовать интерфейс
  2. передают действительный класс в PrintListToConsole
    class MyRenderer : PrintListConsoleRender<int> {
        public String Render(int input) {
            return "Number: " + input;
        }
    }
    
    class Program {
        static void Main(string[] args) {
            var list = new List<int> { 1, 2, 3 };
            var printer = new PrintListToConsole<int>();
            printer.SetRenderer(new MyRenderer());
            printer.PrintToConsole(list);
            string result = Console.ReadLine();   
        }   
    }
    

. Использование Func намного проще

. Внутри компонента вы определяете параметр type Func<T,String>, который представляет собой интерфейс функции, которая принимает входной параметр типа T и возвращает строку (вывод для консоли)

class PrintListToConsole<T> {

    private Func<T, String> _renderFunc;

    public void SetRenderFunc(Func<T, String> r) {
        // this is the point where I can set the render mechanism
        _renderFunc = r;
    }

    public void Print(List<T> list) {
        foreach (var item in list) {
            Console.Write(_renderFunc(item));
        }
    }
}

Когда разработчик использует ваш компонент, он просто переходит к компонент реализует тип Func<T, String>, то есть функционал на котором создается вывод для консоли.

class Program {
    static void Main(string[] args) {
        var list = new Array[1, 2, 3];
        var printer = new PrintListToConsole<int>();
        printer.SetRenderFunc((o) => "Number:" + o);
        printer.Print();
        string result = Console.ReadLine();
    }
}

Func<T> позволяет вам определять общий интерфейс метода «на лету». Вы определяете тип ввода и тип вывода. Простой и лаконичный.

6
ответ дан Marco Staffoli 4 September 2018 в 08:37
поделиться

Func<T1,R> и другие предопределенные общие Func делегаты (Func<T1,T2,R>, Func<T1,T2,T3,R> и другие) являются универсальными делегатами, которые возвращают тип последнего общего параметра.

Если у вас есть функция, которая должна возвращать разные типы, в зависимости от параметров, вы можете использовать делегат Func, указав тип возврата.

11
ответ дан Oded 4 September 2018 в 08:37
поделиться

Это только предопределенный общий делегат. Используя его, вам не нужно объявлять каждого делегата. Существует еще один предопределенный делегат, Action<T, T2...>, который является тем же, но возвращает void.

6
ответ дан Stefan Steinegger 4 September 2018 в 08:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: