horgh
horgh

Reputation: 18533

How to make a derived concrete class implicitly cast a generic base class?

I have a base abstract generic class, which shoud give an ability to get the identifier of an object through an expression:

public abstract class Entity<TId> where TId : IEquatable<TId>
{
    protected abstract Expression<Func<Entity<TId>, TId>> GetEntityId();
}

But when I try to derive from it (and implement the abstract method):

public class IntEntity : Entity<int>
{
    public int Id { get; set; }

    protected override Expression<Func<Entity<int>, int>> GetEntityId()
    {
        Expression<Func<IntEntity, int>> exp = e => e.Id;
        return exp; // CS0029 error
    }
}

I get CS0029 compile error, saying

Cannot implicitly convert type 'System.Linq.Expressions.Expression<System.Func<ConsoleApplication1.IntEntity,int>>' to 'System.Linq.Expressions.Expression<System.Func<ConsoleApplication1.Entity<int>,int>>'

Is there anything I can do about this?

Upvotes: 3

Views: 494

Answers (1)

SLaks
SLaks

Reputation: 887469

That is inherently unsafe.

Had that been legal, you would be able to pass a different class inheriting Entity<int> to your function that can only accept IntEntitys.

Instead, you can use the CRTP:

public abstract class Entity<TEntity, TId> 
    where TId : IEquatable<TId> 
    where TEntity : Entity<TEntity, TId>
{
    protected abstract Expression<Func<TEntity, TId>> GetEntityId();
}

Upvotes: 6

Related Questions