包含Generic方法的通用接口需要相同的约束吗?

时间:2013-06-19 01:14:08

标签: c# entity-framework generics

我定义了以下界面。

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()之后建模的,它有自己的约束,但这些约束没有应用于泛型方法本身。

我按照以下答案提供了选项3:

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

}

HTH

1 个答案:

答案 0 :(得分:6)

删除<T> Set<T>中的DbSet<T> Set<T>()或<{em>> TSet<T>T另一个名称,你应该没问题。否则,您要从T中的IDbContext<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

Alternatively,从public interface IDbContext : IDisposable { DbSet<T> Set<T>() where T : class int SaveChanges(); } 删除通用参数:

{{1}}

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