Próbowałem to zbudować na odpowiedzi @Andrey Naumov . Może to jest niewielka poprawa.
public sealed class Lambda<S>
{
public static Func<S, T> CreateFunc<T>(Func<S, T> func)
{
return func;
}
public static Expression<Func<S, T>> CreateExpression<T>(Expression<Func<S, T>> expression)
{
return expression;
}
public Func<S, T> Func<T>(Func<S, T> func)
{
return func;
}
public Expression<Func<S, T>> Expression<T>(Expression<Func<S, T>> expression)
{
return expression;
}
}
Gdzie parametr typu S
jest parametrem formalnym (parametrem wejściowym, który jest minimalny wymagany do wywnioskowania pozostałych typów). Teraz możesz to nazwać tak:
var l = new Lambda<int>();
var d1 = l.Func(x => x.ToString());
var e1 = l.Expression(x => "Hello!");
var d2 = l.Func(x => x + x);
//or if you have only one lambda, consider a static overload
var e2 = Lambda<int>.CreateExpression(x => "Hello!");
Możesz mieć dodatkowe przeciążenia dla Action<S>
i Expression<Action<S>>
podobnie w tej samej klasie. Na drugi zbudowany w typów delegatów i wypowiedzi, trzeba będzie napisać osobne zajęcia, takie jak Lambda
, Lambda<S, T>
, Lambda<S, T, U>
itd.
Zaleta tego, którą widzę w porównaniu z oryginalnym podejściem:
Jedna specyfikacja typu mniej (należy podać tylko parametr formalny).
Co daje ci swobodę użycia go przeciwko każdemu Func<int, T>
, nie tylko wtedy, gdy T
jest powiedz string
, jak pokazano na przykładach.
Obsługuje wyrażenia od razu. We wcześniejszym podejściu będziesz musiał ponownie określić typy, takie jak:
var e = Lambda<Expression<Func<int, string>>>.Cast(x => "Hello!");
//or in case 'Cast' is an instance member on non-generic 'Lambda' class:
var e = lambda.Cast<Expression<Func<int, string>>>(x => "Hello!");
dla wyrażeń.
Rozszerzanie klasy dla innych typów delegatów (i wyrażeń) jest podobnie nieporęczne, jak powyżej.
var e = Lambda<Action<int>>.Cast(x => x.ToString());
//or for Expression<Action<T>> if 'Cast' is an instance member on non-generic 'Lambda' class:
var e = lambda.Cast<Expression<Action<int>>>(x => x.ToString());
W moim podejściu musisz zadeklarować typy tylko raz (to za jeden mniej na Func
s).
Innym sposobem na wdrożenie odpowiedzi Andreya jest nie przejście w pełni na ogólny
public sealed class Lambda<T>
{
public static Func<Func<T, object>, Func<T, object>> Func = x => x;
public static Func<Expression<Func<T, object>>, Expression<Func<T, object>>> Expression = x => x;
}
Więc wszystko sprowadza się do:
var l = Lambda<int>.Expression;
var e1 = l(x => x.ToString());
var e2 = l(x => "Hello!");
var e3 = l(x => x + x);
To jeszcze mniej pisania, ale tracisz pewne bezpieczeństwo typów, a imo, to nie jest tego warte.