Вы можете использовать закрытый абстрактный абстрактный класс вместо перечисления, например:
sealed abstract class Constraint(val name: String, val verifier: Int => Boolean)
case object NotTooBig extends Constraint("NotTooBig", (_ < 1000))
case object NonZero extends Constraint("NonZero", (_ != 0))
case class NotEquals(x: Int) extends Constraint("NotEquals " + x, (_ != x))
object Main {
def eval(ctrs: Seq[Constraint])(x: Int): Boolean =
(true /: ctrs){ case (accum, ctr) => accum && ctr.verifier(x) }
def main(args: Array[String]) {
val ctrs = NotTooBig :: NotEquals(5) :: Nil
val evaluate = eval(ctrs) _
println(evaluate(3000))
println(evaluate(3))
println(evaluate(5))
}
}
Лямбда-выражение может или быть преобразовано в тип делегата или дерево выражений - но оно должно знать который тип делегата. Просто знание подписи не достаточно. Например, предположите, что я имею:
public delegate void Action1();
public delegate void Action2();
...
Delegate x = () => Console.WriteLine("hi");
, Чем Вы ожидали бы, что конкретный тип объекта, упомянутого x
, будет? Да, компилятор мог генерировать новый тип делегата с соответствующей подписью, но это редко полезно, и Вы заканчиваете с меньшей возможностью для проверки ошибок.
, Если Вы хотите помочь звонить Control.Invoke
с Action
, самая легкая вещь сделать, добавляет дополнительный метод для Управления:
public static void Invoke(this Control control, Action action)
{
control.Invoke((Delegate) action);
}
Усталый от кастинга лямбд много раз?
public sealed class Lambda<T>
{
public static Func<T, T> Cast = x => x;
}
public class Example
{
public void Run()
{
// Declare
var c = Lambda<Func<int, string>>.Cast;
// Use
var f1 = c(x => x.ToString());
var f2 = c(x => "Hello!");
var f3 = c(x => (x + x).ToString());
}
}