The following code already works but I think specifying int
in the following
var repo = new Repository<Student, int>(students);
is a bit redundant. I want to simplify as follows:
var repo = new Repository<Student>(students);
How should I modify the IRepository
and Repository
below to achieve what I want?
Minimal Working Example:
class Entity<TKey>
{
public TKey Id { get; set; } = default!;
}
interface IRepository<TEntity, TKey> where TEntity : Entity<TKey>
{
IEnumerable<TEntity> GetAll();
}
class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : Entity<TKey>
{
private readonly IEnumerable<TEntity> data;
public Repository(IEnumerable<TEntity> data) => this.data = data;
public IEnumerable<TEntity> GetAll() => data;
}
class Student : Entity<int>
{
public string Name { get; set; } = default!;
}
class Program
{
static void Main()
{
var students = new Student[]
{
new Student { Name="Andy"},
new Student { Name="Bob"},
new Student { Name="Cindy"}
};
var repo = new Repository<Student, int>(students);
}
}
Note: My entities can have primary keys of type string
, int
, Guid
, etc.
CodePudding user response:
c# cannot do partial type inference. In some cases you can do a workaround by creating a object with one generic type parameter, and using a method on this that lets you infer the other. But I do not see any way to do that in this specific case.
But you could perhaps use a static method to let you infer both types, :
public static class Repository{
public static Repository<TEntity, TKey> Create<TEntity, TKey>(IEnumerable<TEntity> data)
where TEntity : Entity<TKey>
=> new Repository<TEntity, TKey>(data);
}
...
var repo = Repository.Create(students);
The thing here is that constructors cannot do type inference, but static methods can.