我为我的存储库创建了此接口。逆向值类型
public interface IRepository<T, in TKey> where T: class
{
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
IEnumerable<T> FindAll();
T FindSingle(TKey id);
void Create(T entity);
void Delete(T entity);
void Update(T entity);
}
FindSingle
方法接受一个ID,它将用于在主键上搜索。通过使用in
我期望我只能被允许通过参考类型TKey
。出于好奇,我决定创建一个具体类并将其指定为int,以便我可以看到异常。
我抬头MSDN它指定这个不应该工作
协变和逆变的泛型类型参数都支持引用类型,但不支持值类型。
类我创建看起来像这样
public class ProjectRepository : IRepository<Project,int>
{
public IEnumerable<Project> Find(Expression<Func<Project, bool>> predicate)
{
throw new NotImplementedException();
}
public IEnumerable<Project> FindAll()
{
throw new NotImplementedException();
}
public Project FindSingle(int id)
{
throw new NotImplementedException();
}
public void Create(Project entity)
{
throw new NotImplementedException();
}
public void Delete(Project entity)
{
throw new NotImplementedException();
}
public void Update(Project entity)
{
throw new NotImplementedException();
}
}
为什么我没有得到建一个例外具有指定TKey
为值类型?另外,如果我从我的参数中删除了in
,我失去了什么? MSDN文档说,反转式允许使用派生类型较少,但肯定通过删除in
我可以传入任何类型,因为它仍然是通用的。
这可能表现出对逆变和协变性缺乏了解,但它让我有点困惑。
我怀疑是编译器并没有抱怨,因为'int'是'sealed'等都将永不进入共同或禁忌变种使用。 * Variance *是关于当* variant *类型的派生类型替换基类型时,编译器如何处理一般类型类的用法。例如。 'List animals = new List ();'是协变的。和'((IRepository )repo).Update(animal);'是逆变的。 –
@KeithPayne:'列表'是一类。类和协变不支持,因此代码不会编译。分配的目标需要是协变接口。 –
@DanielHilgarth谢谢丹尼尔。 这个例子应该是IEnumerable animals = new List ();' 而第二个例子也不是很好。 '((IUpdateOnlyRepository )repo).Update(animal);'更好,因为使用普通的旧版本库意味着也会返回变体类型的方法。 –