Ho provato a costruire questo sulla risposta di @Andrey Naumov . Potrebbe essere un leggero miglioramento.
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;
}
}
Dove tipo parametro S
è il parametro formale (il parametro di input, che è il minimo richiesto per dedurre il resto dei tipi). Ora puoi chiamarlo come:
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!");
Puoi avere sovraccarichi aggiuntivi per Action<S>
e in Expression<Action<S>>
modo simile nella stessa classe. Per altro costruito in tipi delegato e di espressione, si dovrà scrivere classi separate piace Lambda
, Lambda<S, T>
,Lambda<S, T, U>
etc.
Vantaggio di questo che vedo rispetto all'approccio originale:
Una specifica di tipo in meno (è necessario specificare solo il parametro formale).
Il che ti dà la libertà di usarlo contro chiunque Func<int, T>
, non solo quando T
si dice string
, come mostrato negli esempi.
Supporta immediatamente le espressioni. Nell'approccio precedente dovrai specificare di nuovo i tipi, come:
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!");
per le espressioni.
L'estensione della classe per altri tipi di delegati (ed espressioni) è altrettanto complicata come sopra.
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());
Nel mio approccio devi dichiarare i tipi solo una volta (anche quella in meno per Func
s).
Un altro modo per implementare la risposta di Andrey è come non essere completamente generici
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;
}
Quindi le cose si riducono a:
var l = Lambda<int>.Expression;
var e1 = l(x => x.ToString());
var e2 = l(x => "Hello!");
var e3 = l(x => x + x);
È ancora meno digitando, ma perdi una certa sicurezza di tipo, e imo, non ne vale la pena.