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

时间:2016-09-25 19:49:03

标签: c# .net generics

考虑以下情况:

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>

的地方

2 个答案:

答案 0 :(得分:1)

在你的例子中:

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);
}

答案 1 :(得分:-1)

因为C#规范要求构造函数参数。关于这个问题的规范答案是Why can't the C# constructor infer type?

值得注意的是几件事:我们几乎在C#6中得到它。你可以使用一个简单地调用构造函数的静态方法来破解它。例如

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);
    }
}

为方便起见,我将它放在同名的非泛型类型上。