Tentei construir isso com base na resposta de @Andrey Naumov . Pode ser que isso seja uma ligeira melhora.
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;
}
}
Onde type parameter S
é o parâmetro formal (o parâmetro de entrada, que é mínimo necessário para inferir o restante dos tipos). Agora você pode chamar assim:
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!");
Você pode ter sobrecargas adicionais para Action<S>
e da Expression<Action<S>>
mesma forma na mesma classe. Por outro construído em tipos de delegado e de expressão, você terá que escrever classes separadas como Lambda
, Lambda<S, T>
, Lambda<S, T, U>
etc.
Vantagem disso eu vejo sobre a abordagem original:
Uma especificação de tipo a menos (somente o parâmetro formal precisa ser especificado).
O que lhe dá a liberdade de usá-lo contra qualquer um Func<int, T>
, não apenas quando T
é dito string
, como mostra os exemplos.
Suporta expressões imediatamente. Na abordagem anterior, você precisará especificar tipos novamente, como:
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!");
para expressões.
Estender a classe para outros tipos de delegados (e expressões) é igualmente complicado como acima.
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());
Na minha abordagem, você deve declarar tipos apenas uma vez (menos um para Func
s).
Outra maneira de implementar a resposta de Andrey é como não ser totalmente genérico
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;
}
Então, as coisas se reduzem a:
var l = Lambda<int>.Expression;
var e1 = l(x => x.ToString());
var e2 = l(x => "Hello!");
var e3 = l(x => x + x);
Isso é ainda menos digitado, mas você perde certo tipo de segurança e , imo, isso não vale a pena.