Jam*_*mes 4 .net c# contravariance
我为我的存储库创建了这个界面.
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);
}
Run Code Online (Sandbox Code Playgroud)
该FindSingle方法接受一个ID,该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();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我没有在指定TKey为值类型的构建上获得异常?另外,如果我in从参数中删除了我丢失的内容?MSDN文档说逆向允许使用较少派生的类型,但肯定通过删除in我可以传递任何类型,因为它仍然是通用的.
这可能表现出对逆变和协方差的缺乏理解,但它让我有点困惑.
协方差和逆变对价值类型没有多大意义,因为它们都是密封的.虽然从文档中不清楚,但使用a struct作为co/contravariant类型是有效的,它并不总是有用.您引用的文档很可能是指以下内容无效:
public struct MyStruct<in T>
Run Code Online (Sandbox Code Playgroud)
逆变法意味着您可以执行以下示例:
IRepository<string, Base> b = //something
IRepository<string, Derived> d = b;
Run Code Online (Sandbox Code Playgroud)
由于没有任何东西可以衍生出来int,你可以使用IRepository<string, int>,但只能作为IRepository<string, int>.
协方差意味着你可以做相反的,例如IEnumerable<T>是out T,这是协变的.您可以执行以下操作:
IEnumerable<Derived> d = //something
IEnumerable<Base> b = d;
Run Code Online (Sandbox Code Playgroud)
如果你想限制都TKey和T对classES(引用类型),你应该包括第二限制:
public interface IRepository<T, in TKey>
where T : class
where TKey : class
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
229 次 |
| 最近记录: |