包含泛型方法的泛型接口需要相同的约束



我定义了以下接口:

IDbContext

public interface IDbContext<T> : IDisposable where T : class
{
    DbSet<T> Set<T>();
    int SaveChanges();
}

由TestContext间接实现,注意TestContext派生自System.Data.Entity.DbContext。

public class TestContext: DbContext,IDbContext<Foo>
{
}

Foo是某个实体

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

编译器抛出以下错误:

类型'T'必须是引用类型才能将其用作形参泛型类型或方法中的'TEntity'"System.Data.Entity。DbSet"TestContext.cs

类型'T'必须是引用类型才能将其用作形参泛型类型或方法中的'TEntity'"System.Data.Entity。DbSet"IDbContext.cs

方法的类型参数"TEntity"的约束'System.Data.Entity.DbContext.Set()'必须匹配接口方法的类型参数"T"的约束"Domain.Logic.Repositories.IDbContext.Set()"。考虑使用显式接口实现。
EntityFramework.dll

当我将约束添加到IDbContext接口中的Generic方法时,错误就会消失:

public interface IDbContext<T> : IDisposable where T : class
{
    DbSet<T> Set<T>() where T : class;
    int SaveChanges();
}

我很困惑,为什么我需要显式地定义方法上的约束,当它定义在类级别?


根据这些评论,我意识到自己犯了一个错误。

我完全忽略了DbContext.Set()方法上的类型参数。泛型方法的类型参数不同于它的类/接口类型参数(如果有的话),因此应该命名为不同的类型参数。在我的例子中,我有两个问题:1)我有一个泛型接口,具有相同参数名称的泛型类型方法。2)泛型方法本身是在DbContext.Set()之后建模的,DbContext.Set()有自己的约束,但是这些约束不应用于泛型方法本身。

我选择了选项3,如下面的答案所示:

public interface IDbContext : IDisposable {
DbSet<T> Set<T>() where T : class
int SaveChanges();

}

HTH

DbSet<T> Set<T>()中删除Set<T>中的<T> Set<T>中给T一个不同的名称,您应该没问题。否则,您定义的T IDbContext<T>中的T参数不同。这就是为什么编译器需要第二个约束,它认为这是一个不同的T。因此,您需要以下两个选项之一。第一:

public interface IDbContext<T> : IDisposable where T : class {
    DbSet<T> Set();
    int SaveChanges();
}

public interface IDbContext<T> : IDisposable where T : class {
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
    int SaveChanges();
}

或者,从IDbContext中删除通用参数:

public interface IDbContext : IDisposable {
    DbSet<T> Set<T>() where T : class
    int SaveChanges();
}

根据你的意见,后者似乎更符合你的需求。

最新更新