С# Встроенная оценка лямбда

В разное время во время программирования на С# я обнаружил себя в ситуациях, когда я хотел бы определить лямбда (или анонимный делегат) и вызвать его в той же строке. На данный момент "самый чистый" способ, которым я был в состоянии сделать это, выглядит следующим образом:

bool foo_equals_bar = new Func<String, bool>(str => str.Equals("foo"))("bar");

Мне бы хотелось, чтобы я мог написать что-то вроде следующего:

bool foo_equals_bar = (str => str.Equals("foo"))("bar");

К сожалению, это не работает. Я хотел бы знать:

  • Есть ли более простой способ написания строки выше?
  • Что возвращается из (str => str.Equals("foo")), которое может быть использовано для инициализации Func<String, bool>, но не может быть оценено как Func<String, bool>?

Я должен указать, что я работаю на С# 3 (VS2008), поэтому, если решение существует только в С# 4, укажите это. (Я бы все еще хотел знать, даже если решение не доступно мне в данный момент).

Спасибо

Ответы

Ответ 1

str => str == "A" 

совпадает с

delegate (string str) { return str == "A";};

Нет, нет способа получить только лямбду, поскольку компилятор не знает, какой тип str, если вы только что сказали

bool result = (str => str == "A")("B");

EDIT:

Да, вы можете добавлять типы к лямбда-выражениям, например (string str) => str == "A";, но тем не менее они не могут быть неявными по какой-либо причине. Не знаю, почему. Спасибо за комментарий, Юрий.

Ответ 2

Вам понадобится набор вспомогательных методов, чтобы заставить компилятор выводить лямбда-типы, например:


public static class Functional
{
    public static Func<TResult> Lambda<TResult>(Func<TResult> func)
    {
        return func;
    }

    public static Func<T, TResult> Lambda<T, TResult>(Func<T, TResult> func)
    {
        return func;
    }

    public static Func<T1, T2, TResult> Lambda<T1, T2, TResult>(Func<T1, T2, TResult> func)
    {
        return func;
    }
}

Теперь вы можете написать:


bool foo_equals_bar = Functional.Lambda(str => str.Equals("foo"))("bar");

Ответ 3

Что возвращается (str = > str.Equals( "foo" )) такой, что может быть используется для инициализации Func, но не может быть оценен как Func

Просто используя встроенные типы, есть:

Expression<Func<string, bool>> a = str => str.Equals("foo");
Expression<Predicate<string>> b = str => str.Equals("foo");
Expression<Action<string>> c = str => str.Equals("foo");
Func<string, bool> a1 = str => str.Equals("foo");
Predicate<string> b1 = str => str.Equals("foo");
Action<string> c1 = str => str.Equals("foo");

Все из которых являются допустимыми интерпретациями лямбда-выражения. Это просто встроенные типы, которые я могу придумать с головы. Там также есть любой делегат, который соответствует подписи.

Ответ 4

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

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

И в любом случае:

bool foo_equals_bar = "bar".Equals("foo");

является более читаемым, чем *:

bool foo_equals_bar = (str => str.Equals("foo"))("bar");

* при условии, что такой синтаксис возможен

Ответ 5

Вы должны наложить лямбду на функцию или делегата
((Func<string, bool>)(str => str.Equals("bar")))("baz")