J'ai essayé de me baser sur la réponse de @Andrey Naumov . C'est peut-être une légère amélioration.
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;
}
}
Où le paramètre type S
est le paramètre formel (le paramètre d'entrée, qui est au minimum requis pour déduire le reste des types). Maintenant, vous pouvez l'appeler comme:
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!");
Vous pouvez avoir des surcharges supplémentaires pour Action<S>
et Expression<Action<S>>
de la même manière dans la même classe. Pour les autres types intégrés de délégués et d' expression, vous devrez écrire des classes séparées comme Lambda
, Lambda<S, T>
, Lambda<S, T, U>
etc.
Avantage de cela, je vois sur l'approche originale:
Une spécification de type en moins (seul le paramètre formel doit être spécifié).
Ce qui vous donne la liberté de l'utiliser contre n'importe quel Func<int, T>
, pas seulement quand T
c'est-à-dire string
, comme le montrent les exemples.
Prend en charge les expressions immédiatement. Dans l'approche précédente, vous devrez spécifier à nouveau les types, comme:
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!");
pour les expressions.
L'extension de la classe pour d'autres types de délégués (et d'expressions) est également fastidieuse, comme ci-dessus.
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());
Dans mon approche, vous ne devez déclarer les types qu'une seule fois (cela aussi un de moins pour Func
s).
Une autre façon de mettre en œuvre la réponse d'Andrey est de ne pas devenir complètement générique
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;
}
Les choses se réduisent donc à:
var l = Lambda<int>.Expression;
var e1 = l(x => x.ToString());
var e2 = l(x => "Hello!");
var e3 = l(x => x + x);
C'est encore moins de taper, mais vous perdez certains types de sécurité, et à mon avis, cela n'en vaut pas la peine.