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

C# 包含泛型方法的泛型接口需要相同的约束?,c#,entity-framework,generics,C#,Entity Framework,Generics,我定义了以下接口 IDbContext public interface IDbContext<T> : IDisposable where T : class { DbSet<T> Set<T>(); int SaveChanges(); } 编译器抛出以下错误: 类型“T”必须是引用类型才能将其用作参数 泛型类型或方法中的“tenty” 'System.Data.Entity.DbSet'TestContext.cs 类型“T”必须是引用

我定义了以下接口

IDbContext

public interface IDbContext<T> : IDisposable where T : class
{
    DbSet<T> Set<T>();
    int SaveChanges();
}
编译器抛出以下错误:

类型“T”必须是引用类型才能将其用作参数 泛型类型或方法中的“tenty” 'System.Data.Entity.DbSet'TestContext.cs

类型“T”必须是引用类型才能将其用作参数 泛型类型或方法中的“tenty” 'System.Data.Entity.DbSet'IDbContext.cs

方法类型参数“tenty”的约束 “System.Data.Entity.DbContext.Set”必须与 接口方法的类型参数“T”的约束 'Domain.Logic.Repositories.IDbContext.Set'。 请考虑使用显式接口实现。 EntityFramework.dll

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

public interface IDbContext<T> : IDisposable where T : class
{
    DbSet<T> Set<T>() where T : class;
    int SaveChanges();
}
我很困惑,为什么我需要显式地定义在类级别定义的方法上的约束

更新 根据这些评论,我意识到我犯了错误

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

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

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

HTH

在DbSet Set中删除in Set,或者在Set中为T指定一个不同的名称,这样就可以了。否则,您将定义一个与IDbContext中的T参数不同的T。这就是为什么编译器需要第二个约束,它认为它是一个不同的T。因此,您需要以下两个选项之一。第一:

public interface IDbContext<T> : IDisposable where T : class {
    DbSet<T> Set();
    int SaveChanges();
}
根据您的需要,后者似乎更适合您的需要。

在DbSet Set中删除in Set或在Set中给T一个不同的名称,您应该会很好。否则,您将定义一个与IDbContext中的T参数不同的T。这就是为什么编译器需要第二个约束,它认为它是一个不同的T。因此,您需要以下两个选项之一。第一:

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

基于你的,后者似乎更适合您的需要。

他也可以理解为T。@Romoku:我认为最好避免重新定义T。在可以调用IDbContext的地方维护它会很混乱和困难。设置更不用说在类实现中有两个不相关的类型T。@Jason:我很抱歉尝试基于以下通用方法定义契约:System.Data.Entity.DbContext.Set,其签名为:public DbSet Set,其中tenty:class;删除T会使它成为一个不同的方法。@Romoku不起作用,DbSet甚至不能是协变的,因为它是一个类,而不是一个接口。@Karl嗯,该方法是泛型的,因为DbContext通常不限于单个实体。所以错误的部分很可能是将IDbContext设置为泛型。他也可以将其设置为T。@Romoku:我认为最好避免重新定义T。在IDbContext这样的调用中,将很容易混淆和维护。设置更不用说在类实现中有两个不相关的T类型。@Jason:我试图基于以下通用方法定义契约:System.Data.Entity.DbContext.Set,其签名为:public DbSet Set,其中tenty:class;删除T会使它成为一个不同的方法。@Romoku不起作用,DbSet甚至不能是协变的,因为它是一个类,而不是一个接口。@Karl嗯,该方法是泛型的,因为DbContext通常不限于单个实体。因此,错误的部分很可能使IDbContext成为泛型。您的接口会导致警告。如果你看它,它会告诉你到底是怎么回事。下次,不要忽略警告。您的界面会导致警告。如果你看它,它会告诉你到底是怎么回事。下次,不要忽略警告。
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();
}
public interface IDbContext : IDisposable {
    DbSet<T> Set<T>() where T : class
    int SaveChanges();
}