Как я могу использовать расширения linq без лямбды?

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

Я хотел бы попробовать использовать метод расширения Where() без лямбды, просто чтобы посмотреть, как он будет выглядеть, но я не могу понять, как заставить его скомпилироваться и работать должным образом. Этот пример не имеет смысла, поэтому не пытайтесь выяснить какую-либо логику.

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

Что меня смущает, так это то, что условие Where() принимает Func<int,bool>, но метод возвращает IEnumerable<int>? Способ, которым определяется Func, он принимает один int и возвращает bool. Было бы больше смысла для меня, если бы это было Func<int, bool, IEnumberable<string>>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Delegates
{
    public class Learning
    {
        /// <summary>
        /// Predicates - specialized verison of Func
        /// </summary>
        public static void Main()
        {
            List<int> list = new List<int> { 1, 2, 3 };

            Func<int, bool> someFunc = greaterThanTwo;
            IEnumerable<int> result = list.Where(someFunc.Invoke(1));

        }


        static IEnumerable<int> greaterThanTwo(int arg, bool isValid)
        {
              return new List<int>() { 1 };
        }

    }
}

Обновленный код

public class Learning
    {
        /// <summary>
        /// Predicates - specialized verison of Func
        /// </summary>
        public static void Main()
        {
            // Without lambda
            List<int> list = new List<int> { 1, 2, 3 };

            Func<int, bool> someFunc = greaterThanTwo;
            // predicate of type int
            IEnumerable<int> result = list.Where(someFunc);

        }


        static bool greaterThanTwo(int arg, bool isValid)
        {
            return true;
        }

    }

Я получаю следующую ошибку:

Нет перегрузки для 'greatThanTwo' соответствует делегату 'System.Func'

4 ответа

Решение

Where принимает функцию, которая принимает один элемент (в этом случае int) в качестве параметра и логическое значение в качестве возвращаемого типа. Это называется предикатом - он дает ответ "да" или "нет", который можно применять снова и снова к последовательности элементов одного типа.

Вы ошиблись в greaterThanTwo функция - принимает два аргумента, а не один - и возвращает IEnumerable<int> - так что это абсолютно несовместимо с Func<int, bool>, Это должно занять int и вернуть bool - опять же, это предикат (см. выше).

Как только вы разберетесь с этим, ваша другая проблема Invoke - вы ничего не вызываете - вы передаете делегат (указатель) методу и его внутренностям Where позаботится о том, чтобы вызвать его, когда это необходимо.

Попробуй это:

static bool greaterThanTwo(int arg)
{
    return (arg > 2);
}

//snip

Func<int, bool> someFunc = greaterThanTwo;
IEnumerable<int> result = list.Where(someFunc);

Определение Func<T, TResult> определяет делегата, который принимает один параметр типа T и возвращает результат типа TResult, Linqs Where предложение определяется (косвенно через метод расширения) в отношении IEnumerable<T> и принимает параметр (базовая версия Where) типа Func<T, bool> который в основном говорит, что функция должна принимать параметр типа IEnumerable и вернуть bool значение.

Чтобы ваш пример работал:

bool greaterThanTwo(int arg)
{
    // this needs to be a boolean operation against the arg
    return arg > 2;
}

// and invoke like
list.Where(greaterThanTwo);

Func<int, bool> означает, что у вас есть функция, которая принимает int и возвращает bool. Если вы хотите добавить больше аргументов в свою функцию, вы можете перечислить их, однако последний общий тип, который вы определили, является типом возврата этой функции. Ваш метод будет выглядеть примерно так, если вы захотите определить его как Func, Func<int, bool, IEnumerable<int>> Ваша функция должна выглядеть примерно так.

namespace Delegates
{
    public class Learning
    {
        /// <summary>
        /// Predicates - specialized verison of Func
        /// </summary>
        public static void Main()
        {
            List<int> list = new List<int> { 1, 2, 3 };

            Func<int, bool> someFunc = greaterThanTwo;
            IEnumerable<int> result = list.Where(someFunc);

        }


        static bool greaterThanTwo(int arg)
        {
              return (arg > 2);
        }

    }
}

Where() Функция выполняет лямбду один раз для каждого элемента. Если вы хотите вернуться, скажите List<int> вы бы использовали Aggregate() вместо этого, который обеспечивает эту функциональность. Но Where() автоматически добавляет или не добавляет элемент на основе логического возвращаемого значения вашей лямбды.

Другие вопросы по тегам