I know there are plenty of questions around generics, inheritance and type inference. But I really struggle to understand some reasoning behind the current behavior. I will point out in the example what I want to achieve by the end.
interface IState { }
interface IEntity<T> where T : IState
{
T Get();
void Set(T model);
}
interface IRepository<T>
{
T GetById(Guid id);
void Save(T model);
}
class RepositoryA<T, V>
: IRepository<T> where T
: IEntity<V> where V
: IState
{
public T GetById(Guid id) {}
public void Save(T model) {}
}
class RepositoryB<T>
: IRepository<T> where T
: IEntity<IState>
{
public T GetById(Guid id) {}
public void Save(T model) {}
}
class Program
{
static void Main(string[] args)
{
IRepository<FireEntity> repoA = new RepositoryA<FireEntity, FireState>(); // Compiles fine
IRepository<FireEntity> repoB = new RepositoryB<FireEntity>(); // Compilation Error: FireEntity must be convertible to IEntity<IState>
IEntity<FireState> a = new FireEntity(); // Compiles fine
IEntity<IState> b = new FireEntity(); // fails to convert
}
class FireState: IState {}
class FireEntity : IEntity<FireState>
{
public FireState Get() {}
public void Set(FireState model) {}
}
}
I would like to use the syntax of RepositoryB<T>
but as you can see it the implicit conversion doesn't work like that.
I cannot get my head around how to cheat
the compiler and get the desired syntax.
Any workarounds?
P.S. Obviously this is an excerpt of the real code and I cannot use Covariant out parameters for T