为什么我需要在泛型类上显式地定义泛型参数'

本文关键字:泛型 定义 参数 泛型类 为什么 | 更新日期: 2023-09-27 18:08:39

考虑以下场景:

public interface IEntity<TKey>
{
    TKey { get; set; }
}
public interface IRepository<TEntity, TKey>
      where TEntity : IEntity<TKey>
{
    void Store(TEntity entity);
    void Delete(TKey key);
}

为什么我需要显式地将TKey作为通用参数添加到IRepository ?

编译器不能从TEntity的类型推断或推断出来吗?

我想实现这样的事情:

public interface IRepository<TEntity>
    where TEntity : IEntity<TKey>
{
     void Store(TEntity entity);
     void Delete(TKey key);
}

不像TKey只在运行时被知道:

IRepository<User> userRepo = new ConcreteRepository<User>();

User实现IEntity<string>

为什么我需要在泛型类上显式地定义泛型参数'

在您的示例中:

public interface IRepository<TEntity>
where TEntity : IEntity<TKey> {
   void Store(TEntity entity);
   void Delete(TKey key);
}

TKey是未定义的类型参数。您可以说where TEntity : IEntity<string>,因为string是一个已定义的类型。但是,如果要使用类型参数,则需要首先定义它。

注意编译器不知道这里的TKey是什么。是一种类型吗?它是泛型类型参数吗?

您可能能够做这样的事情,但它将不再是强类型的TEntity。这可能是可接受的,也可能是不可接受的:

public interface IRepository<TKey> {
   void Store(IEntity<TKey> entity);
   void Delete(TKey key);
}

因为c#规范要求构造函数参数是这样的。关于这个问题的标准答案是:为什么c#构造函数不能推断类型?

值得注意的是:我们几乎在c# 6中实现了它。您可以通过使用Static方法来绕过它,该方法只需调用构造函数。例如

public class Entity<TKey>
{
    public Entity(TKey k)
    {
    }
}
public static class Entity
{
    public static Entity<MyKey> Create<MyKey>(MyKey mk)
    {
        return new Entity<MyKey>(mk);
    }
}

为方便起见,我把它放在一个同名的非泛型类型上