0

I'm often building tools with generics and Expression<Func<object, value>> to target properties of the object. I keep struggling on a very stupid limitation of C# (but maybe I am ignorant of the proper solution).

Let's say we have this object:

class MyObject {
  public int NeverNull { get; set; }
  public int? CanBeNull { get; set; }
}

I want to be able to do this:

int? val1 = Foo(o => o.NeverNull);
int? val2 = Foo(o => o.CanBeNull);

I have 2 solutions to do this :

// Solution 1: two overloads
// First overload: for the non-nullable properties
TValue? Foo<TValue>(Expression<Func<MyObject, TValue>> selector)
  where TValue: struct
{ ... }

// Second overload: for the nullable properties
TValue? Foo<TValue>(Expression<Func<MyObject, TValue?>> selector)
  where TValue: struct
{ ... }

And

// Solution 2: using object
TValue? Foo<TValue>(Expression<Func<MyObject, object>> selector)
  where TValue: struct
{ ... }

The first solution implies doubling the logic, which is meh. The second solution implies weak-typing issues and useless boxing/unboxing.

Is there a third, cleaner solution to have a 'nullable-or-not' generic parameter ?

Mose
  • 1,781
  • 3
  • 16
  • 35
  • 1
    Does it need to be constrained to value types? Is there a reason you need any constraints at all? An unconstrained generic method will take any nullable or non-nullable value type. For solution 1, you could forward both `Foo`s to a private, unconstrained generic method to avoid duplication of logic. – Jeff Sep 22 '20 at 17:20
  • Good comment, you pointed an issue in the question. I updated the question => I always need the function to return the nullable version of the related property, whether it's nullable or not. (I won't explain why, that would be off-topic) – Mose Sep 23 '20 at 12:16
  • Both `NeverNull` and `CanBeNull` can be used with the `Expression>` version. You just have to accept that type inference won't work for `NeverNull`. – Damien_The_Unbeliever Sep 23 '20 at 13:08

0 Answers0