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

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

Я хотел бы попробовать использовать метод расширения 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 ]

5 голосов
/ 25 мая 2011

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);
3 голосов
/ 25 мая 2011

Определение 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);
1 голос
/ 25 мая 2011

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);
        }

    }
}
0 голосов
/ 25 мая 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...