开发者

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

开发者 https://www.devze.com 2023-02-19 22:05 出处:网络
Say I have a function such as: public TProperty Foo<TClass, TProperty>(TClass instance, Expression<Func<TClass, TProperty>> expression)

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

Expres开发者_开发问答sion<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.


In cases like these it can be still OK to use method overloading provided the logic is refactored to a private method.

I think you can restrict it on where TProperty : Nullable<TProperty> though I have not checked this


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

0

精彩评论

暂无评论...
验证码 换一张
取 消