1

我定义了以下接口。

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”必须是引用类型才能在泛型类型或方法“System.Data.Entity.DbSet”TestContext.cs 中用作参数“TEntity”

类型“T”必须是引用类型才能在泛型类型或方法“System.Data.Entity.DbSet”IDbContext.cs 中用作参数“TEntity”

方法“System.Data.Entity.DbContext.Set()”的类型参数“TEntity”的约束必须匹配接口方法“Domain.Logic.Repositories.IDbContext.Set()”的类型参数“T”的约束。考虑改用显式接口实现。
实体框架.dll

当我将约束添加到 IDbContext 接口中的通用方法时,错误消失了:

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

我很困惑为什么在类级别定义方法时需要显式定义方法的约束?


更新 根据评论,我意识到我犯的错误。

我完全忽略了 DbContext.Set() 方法的类型参数。泛型方法上的类型参数与其类/接口类型参数不同(如果有),因此应该命名不同。在我的情况下,我遇到了几个问题:1)我有一个通用接口和一个具有相同参数名称的通用类型方法。2) 泛型类型化方法本身是在 DbContext.Set() 之后建模的,它有自己的约束,但这些约束并未应用于泛型方法本身。

我选择了以下答案中提供的选项 3:

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

}

高温高压

4

1 回答 1

6

删除<T>inSet<T>in一个不同的名称,你应该没问题。否则,您定义的 a与中的参数不同。这就是编译器需要第二个约束的原因,它认为它是一个不同的. 因此,您需要以下两个选项之一。第一的:DbSet<T> Set<T>() TSet<T>TTIDbContext<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();
}

根据您的评论,后者似乎更适合您的需求。

于 2013-06-19T01:20:55.620 回答