c# - 逆变值类型

标签 c# .net 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);
}

FindSingle 方法接受一个 ID,该 ID 将用于在主键上进行搜索。通过使用 in,我预计我将只被允许将引用类型作为 TKey 传递。出于好奇,我决定创建一个具体类并将其指定为 int,这样我就可以看到异常。

我查了一下MSDN并且它指定这不应该工作

Covariance and contravariance in generic type parameters are supported for reference types, but they are not supported for value types.

我创建的类看起来是这样的

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 肯定可以传入任何类型,因为它仍然是通用的。

这可能表现出对逆变和协变缺乏理解,但让我有点困惑。

最佳答案

Covariance and contravariance对值类型没有多大意义,因为它们都是密封的。尽管文档中不清楚,但使用 struct 是有效的作为协变/逆变类型,它并不总是有用。您引用的文档很可能指的是以下内容无效:

public struct MyStruct<in T>

逆变意味着您可以执行类似以下示例的操作:

IRepository<string, Base> b = //something
IRepository<string, Derived> d = b;

因为没有任何东西来自 int , 你可以使用 IRepository<string, int> , 但仅作为 IRepository<string, int> .

协方差意味着你可以做相反的事情,例如IEnumerable<T>out T ,这是协变的。您可以执行以下操作:

IEnumerable<Derived> d = //something
IEnumerable<Base> b = d;

如果您试图同时限制 TKeyTclass es(引用类型),你应该包括第二个限制:

public interface IRepository<T, in TKey>
    where T : class
    where TKey : class

关于c# - 逆变值类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18102730/

相关文章:

c# - 使用通用接口(interface)约束时的协变/逆变难题

c# - 如何在 Azure 应用程序见解上忽略 localhost

c# - 使用抽象测试类来运行单元和集成测试有什么值(value)吗?

c# - 在一个 LINQ 查询中获取两列的总和

.net - asp.net登录页面问题

c# - 协变和逆变中的 IsAssignableFrom

c# - 为什么 "Covariance"和 "Contravariance"的概念在实现接口(interface)的方法时适用?

c# - 通过 DMX 从服务器获取数据挖掘模型名称

c# - 关于圆周率计算程序的问题

.Net Standard项目,如何使用System.ServiceModel类