在以下情况下,我们如何从泛型中获益?
public interface IRepository<T> where T : BaseEntity
{
IEnumerable<T> GetAll();
T Get(long id);
void Insert(T entity);
void Update(T entity);
void Delete(T entity);
}
public interface IRepository
{
IEnumerable<BaseEntity> GetAll();
BaseEntity Get(long id);
void Insert(BaseEntity entity);
void Update(BaseEntity entity);
void Delete(BaseEntity entity);
}
我们从第一段代码中获得了什么好处?
答案 0 :(得分:3)
让我们先看一下来电者(使用选项1):
IRepository<SomeEntity> x = ...
var se = x.Get(19);
//I can now immediately call SomeEntity specific methods on se
//Without any casts, and I know it's a SomeEntity and not some other type
或实施者方(使用选项2):
class SomeEntityRepository : IRepository {
...
void Insert(BaseEntity entity) {
//Now I need to check that what I've been passed is
//really a SomeEntity, since that's what I'm a repository for
...
}
}
简而言之,在编译时更好的类型安全性
答案 1 :(得分:1)
这会导致开发人员进行不需要的铸件。考虑是否要在删除中查询以检查该实体是否存在,例如如何访问entity.CustomerId
:
public CustomerRepository : IRepository
{
/* other methods here */
void Delete(BaseEntity entity)
{
var customer = entity as Customer;
// query for customer.CustomerId;
}
}
虽然通用版T
的类型为Customer
,但您无需进行任何投射即可访问该特定类型的属性。
public CustomerRepository : IRepository<Customer>
{
/* other methods here */
void Delete(Customer entity)
{
// No casting
// query for entity.CustomerId;
}
}
注意编译器如何使用T
更改了所有Customer
s。这是仿制药的一个主要优点,您不需要进行铸造。 (例如,非通用集合与List<T>
的历史相同)。