public interface ICardEntity { ... }
public class Card : ICardEntity { ... }
public static class MyExtensions
{
public static List<T> ToList<T>(this IQueryable<T> query) where T : ICardEntity
{ ... }
}
// DbContext
public class ApplicationDbContext : DbContext
{
public DbSet<Card> Cards { get; set; }
}
.....
var list = dbContext.Cards
.ToList(); // -- OK, my extension is called
var list2 = dbContext.Cards
.GroupBy(t => new { Type = t.Type})
.ToList(); // -- Compile error. Why not System.Linq.Enumerable.ToList() is called?
我希望仅为IQueryable调用我的ToList&lt; ICardEntity&gt;,但不适用于IGrouping&lt;&lt;匿名类型:短H&gt;,卡&gt;。为什么约束&#34;其中T:ICardEntity&#34;不工作?
错误讯息:
类型&#39; System.Linq.IGrouping&lt;&lt;匿名类型:短H>, Nucleo.Tests.Models.Card&GT;&#39;不能用作类型参数&#39; T&#39;在里面 泛型类型或方法&#39; MyExtensions.ToList(IQueryable)&#39;。那里 没有隐式引用转换 &#39;&System.Linq.IGrouping LT ;, Nucleo.Tests.Models.Card&GT;&#39;到&#39; ICardEntity&#39;。
答案 0 :(得分:3)
在C#中,通用约束没有超载。您可以重载参数计数和参数类型,但不能重复返回值,通用约束等等。这就是全部。
在重载解析期间,编译器只需要使用ToList(),因为方法的名称以及参数的数量和类型匹配。它之后会验证通用约束,但此时它已经是错误,而不是过载分辨率候选丢失。我不知道如何以更易读的方式表达它。我希望你明白。
经过深思熟虑后 -如果您习惯使用C ++及其模板,那么它不是C ++,并且没有SFINAE可以让它按照您的想法运行。
所有&#39;重载决议&#39;和&#39;方法匹配/查找/等&#39;必须遵循CLS / CLR的规则,所有语言的整个平台,如VB,C#,F3等.CLS / CLR定义了如何查找方法,如何解决重载候选等等。而且,遗憾的是,重载超出泛型类型参数约束,它不包含在规范中。 IIRC将其添加到规范中会在整个平台上产生几个问题(IIRC,类型和方法解析性能),因此没有添加..但这是我记得的。重要的是,它不在语言和运行时平台规范中。