Почему Func <T, bool> вместо Предиката <T>?

Не видя ошибки, я могу быть уверен на 100%, но я думаю, что имя, которое вы включаете в lpsum, вызывает проблему, попробуйте следующее

alloc_prob = pulp.LpProblem("Supplier Allocation Problem", pulp.LpMinimize)

TPC_func = pulp.lpSum(X[s][p]*procCosts[s][p] for s in supplier for p in 
project)
TTC_func = pulp.lpSum(X[s][p]*transCosts[s][p] for s in supplier for p in 
project)
TD_func = pulp.lpSum(X_SEP[c][1]*discountFactor['Bonus / ton [€/t]'][c] for 
c in company)

# Objective function: TPC + TTC - TD -> min
alloc_prob += TPC_func  + TTC_func - TD_func
207
задан abatishchev 18 April 2012 в 02:49
поделиться

4 ответа

В то время как Predicate был представлен в то же самое время, когда List<T> и Array<T>, в .net 2.0, различное Func и Action варианты прибывают из .net 3.5.

Так они Func предикаты используются главным образом для непротиворечивости в операторах LINQ. С .net 3.5, об использовании Func<T> и Action<T> состояния инструкции :

Действительно используют новые типы Func<> и Expression<> LINQ вместо пользовательских делегатов и предикатов

162
ответ дан Shimmy 23 November 2019 в 04:44
поделиться

Я задался вопросом это прежде. Мне нравится эти Predicate<T> делегат - это является хорошим и описательным. Однако необходимо рассмотреть перегрузки Where:

Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

, Который позволяет Вам фильтровать на основе индекса записи также. Это хорошо и последовательно, тогда как:

Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

не был бы.

111
ответ дан Jon Skeet 23 November 2019 в 04:44
поделиться

Конечно, истинная причина для использования Func вместо определенного делегата - то, что C# рассматривает отдельно заявленных делегатов как полностью различные типы.

Даже при том, что Func<int, bool> и Predicate<int> и имеют идентичный аргумент и типы возврата, они не совместимы с присвоением. Таким образом, если бы каждая библиотека объявила свой собственный тип делегата для каждого шаблона делегата, то те библиотеки не были бы в состоянии взаимодействовать, если пользователь не вводит "образующих мост" делегатов для выполнения преобразований.

    // declare two delegate types, completely identical but different names:
    public delegate void ExceptionHandler1(Exception x);
    public delegate void ExceptionHandler2(Exception x);

    // a method that is compatible with either of them:
    public static void MyExceptionHandler(Exception x)
    {
        Console.WriteLine(x.Message);
    }

    static void Main(string[] args)
    {
        // can assign any method having the right pattern
        ExceptionHandler1 x1 = MyExceptionHandler; 

        // and yet cannot assign a delegate with identical declaration!
        ExceptionHandler2 x2 = x1; // error at compile time
    }

, поощряя всех использовать Func, Microsoft надеется, что это облегчит проблему несовместимых типов делегата. Общие делегаты будут играть приятно вместе, потому что они просто подойдутся на основе их типов параметра/возврата.

Это не решает все проблемы, потому что FuncAction) не может иметь out или ref параметры, но они реже используются.

Обновление: в комментариях Svish заявляет:

однако, переключая тип параметра от Func до Предиката и назад, кажется, не имеет значения? По крайней мере, это все еще компилирует без любых проблем.

Да, пока Ваша программа только присваивает методы делегатам, как в первой строке моего Main функция. Компилятор тихо генерирует код к новому, делегат возражает что вперед на методе. Таким образом в моем Main функция, я мог измениться x1, чтобы быть типа ExceptionHandler2, не вызывая проблему.

Однако на второй строке я пытаюсь присвоить первого делегата в другом делегате. Даже мысль, что 2-й тип делегата имеет точно тот же параметр и типы возврата, компилятор, дает ошибку CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'.

, Возможно, это сделает это более ясным:

public static bool IsNegative(int x)
{
    return x < 0;
}

static void Main(string[] args)
{
    Predicate<int> p = IsNegative;
    Func<int, bool> f = IsNegative;

    p = f; // Not allowed
}

Мой метод IsNegative является совершенно хорошей вещью присвоить p и f переменные, пока я делаю так непосредственно. Но тогда я не могу присвоить одну из тех переменных к другому.

30
ответ дан Daniel Earwicker 23 November 2019 в 04:44
поделиться

Совет (в 3,5 и выше) состоит в том, чтобы использовать Action<...> и Func<...> - для "почему?" - одно преимущество состоит в том, что" Predicate<T>" только значимо, если Вы знаете то, что означает "предикат" - иначе необходимо посмотреть на обозреватель объектов (и т.д.) для нахождения signatute.

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

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

28
ответ дан Marc Gravell 23 November 2019 в 04:44
поделиться
Другие вопросы по тегам:

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