0

The following won't compile. It feels like it should. I'm wondering if there is a way around the problem. If possible, I'd prefer to avoid requiring anything to descend from class.

public static Func<DP, R> CastDomain<D, R, DP>(this Func<D, R> function) {
  return (DP dp) => {
    if (dp is D) {
      D d = (D)dp; // Compile error: cannot convert DP to D. But that's crazy as we are inside if (dp is D) {
      return function(d);
    } else {
      // handle the error . . .
    }
  };
}
William Jockusch
  • 26,513
  • 49
  • 182
  • 323
  • You can by casting to object first, e.g. `(D)(object)dp`. I'm sure there must be a duplicate explaining why... – Charles Mager Jun 28 '16 at 08:50
  • Eric Lippert covers exactly this issue [in his blog](https://ericlippert.com/2015/10/14/casts-and-type-parameters-do-not-mix/) – René Vogt Jun 28 '16 at 08:57

2 Answers2

1

// But that's crazy as we are inside if (dp is D)

That doesn't make any difference. There's nothing in the C# specification which says that the validity of a cast can depend on whether you've already checked something.

Basically, you can't convert between generic types like that - you'll have to go via object. It's annoying, but that's the way of things:

D d = (D) (object) dp;
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

Cast can only be applied on classes with inheritance or conversion operator.

If you insist on casting, cast to a common type, eg. object, first.

D d = (D)(object)dp;

If D inherits DP, you can add such constraint to satisfy compiler.

public static Func<DP, R> CastDomain<D, R, DP>(this Func<D, R> function) where D : DP
{
    ...
}
Tommy
  • 3,044
  • 1
  • 14
  • 13