2

Why can't the following expression be converted despite the definition of where TRelatedEntity : Entity?

internal class RelationshipResolver<TEntity> where TEntity : Entity
{
    private readonly List<Expression<Func<TEntity, Entity>>> toOneExpressions = 
        new List<Expression<Func<TEntity, Entity>>>();

    internal RelationshipResolver<TEntity> Include<TRelatedEntity>(
        Expression<Func<TEntity, TRelatedEntity>> oneToOnerelationship)
            where TRelatedEntity : Entity
    {
        toOneExpressions.Add(oneToOnerelationship);
        return this;
    }
...

Compile error for toOneExpressions.Add(oneToOnerelationship):

Argument 1: cannot convert from 'System.Linq.Expressions.Expression<System.Func<TEntity, TRelatedEntity>>' to 'System.Linq.Expressions.Expression<System.Func<TEntity, Microsoft.Xrm.Sdk.Entity>>'
officer
  • 2,080
  • 1
  • 20
  • 29
  • You should check: [Covariance and Contravariance FAQ](https://learn.microsoft.com/en-us/archive/blogs/csharpfaq/covariance-and-contravariance-faq) – Jeroen van Langen Apr 29 '20 at 08:45

1 Answers1

1

The C# compiler does not infer nested generic types.

Expression<Func<TEntity, TRelatedEntity>> is a nested generic type. Neither TEntity nor TRelatedEntity are inferred at compile time. So the compiler does not know Func<TEntity, TRelatedEntity> is assignable to Func<TEntity, Entity>.

For example, without nested generic type, your class should work (though it may not be what you want):

internal class RelationshipResolver<TEntity> where TEntity : Entity
{
    private readonly List<Func<TEntity, Entity>> toOneExpressions =
        new List<Func<TEntity, Entity>>();

    internal RelationshipResolver<TEntity> Include<TRelatedEntity>(
        Func<TEntity, TRelatedEntity> oneToOnerelationship)
        where TRelatedEntity : Entity
    {
        toOneExpressions.Add(oneToOnerelationship);
        return this;
    }
}
weichch
  • 9,306
  • 1
  • 13
  • 25
  • Would there be a better approach other than using `List toOneExpressions`? – officer Apr 29 '20 at 09:26
  • Of the top of my head, I can't think of any solution better than `LambdaExpression`. Unless you do not need to visit `Expression`, in which case you could use `Func<>`. – weichch Apr 29 '20 at 09:30
  • I just need the return type of the Func, so this might work. Thank you. – officer Apr 29 '20 at 09:42