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