C # Generics: how to avoid code duplication when using struct and nullables constraints in lambda expressions

Say I have a function, for example:

public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty>> expression) { ... } 

But then I understand that it should only be used for value types, so I add a restriction

  public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty>> expression) where TProperty : struct { ... } 

But then I discovered that this would not allow me to pass expressions that take the nullable TProperty value. The only way I can 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 have to support two methods that do the same thing, except that it is nullables and the other is not.

Further, I can not extract them into the general method, because, despite the fact that there is a transformation from T to T?, Apparently there is no conversion from

 Expression<Func<T1, T2>> 

to

 Expression<Func<T1, T2?>> 

If the body of these methods is complex, I really do not want to support two separate versions, especially if in fact it is a number of functions.

Is there a way to avoid code duplication and still have a compiler so that the expression should end with either a value type or zero?

(I am currently using C # 3.5, but I am open to later versions if they provide a clean solution.)

+4
source share
3 answers

Depending on what you are doing with this expression, you can force both overloads to call a private top class that accepts the (untyped) LambdaExpression .

+4
source

In such cases, it may still be good to use method overloads, provided that the logic is reorganized into a private method.

I think you can limit it to where TProperty : Nullable<TProperty> , although I have not tested this

+1
source

In .NET 4, Func<P, Q> actually covariant on Q So this idea may work, but alas, Nullable<T> not related to T ( Here's an example.) So Func<P, Q> has no chance of being used where Func<P, Q?> expected.

0
source

Source: https://habr.com/ru/post/1345008/


All Articles