C# 包含泛型方法的泛型接口需要相同的约束?
我定义了以下接口 IDbContextC# 包含泛型方法的泛型接口需要相同的约束?,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”必须是引用
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();
}