Say I have a function such as:
public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty>> expression)
{
...
}
But then I realize it should only be used for value types, so I add a constraint
public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty>> expression)
where TProperty : struct
{
...
}
But I then discover that this won’t let me pass in expressions that take a nullable TProperty. The only way I can see to handle this is to do the following:
public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty?>> expression)
where TProperty : struct
{
...
}
But now I am forced to maintain two methods that do exactly the same thing, except that one deals with nullables, and one doesn’t.
Further more I can’t extract them into a common method, because even though a conversion exists from T to T?, there is apparently no conversion from
Expression<Func<T1, T2>>
to
Expression<Func<T1, T2?>>
If the body of these methods is complicated, I really don’t want to have to maintain two separate versions of them, especially when in fact it is a whole family of functions.
Is there any way to avoid this code duplication and still have the compiler enforce that the expression must end in either a value type or a nullable?
(I am currently using C# 3.5, but am open to more recent versions if they provide a clean solution.)
Depending on what you’re doing with the expression, you could make both overloads call a private overlaod that takes a (untyped)
LambdaExpression.