簡體   English   中英

使用泛型類型在擴展中忽略c#約束

[英]c# constraints ignored in extension with generic type

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 <ICardEntity>調用我的ToList,而不是為IGrouping << anonymous type:short H>,Card>調用。 為什么約束“哪里T:ICardEntity”不起作用?

錯誤信息:

類型'System.Linq.IGrouping << anonymous type:short H>,Nucleo.Tests.Models.Card>'不能在泛型類型或方法'MyExtensions.ToList(IQueryable)'中用作類型參數'T'。 從'System.Linq.IGrouping <,Nucleo.Tests.Models.Card>'到'ICardEntity'沒有隱式引用轉換。

在C#中, 通用約束沒有重載 您可以重載參數計數和參數類型,但不能重復返回值,通用約束等等。這就是全部。

在重載解析期間,編譯器只需要使用ToList(),因為方法的名稱以及參數的數量和類型匹配。 它之后會驗證通用約束,但此時它已經是錯誤,而不是過載分辨率候選丟失。 我不知道如何以更易讀的方式表達它。 我希望你明白。

經過思考 -

如果您習慣使用C ++及其模板,那么它不是C ++,並且沒有SFINAE可以讓它像你想象的那樣工作。

所有'重載解析'和'方法匹配/查找/等'必須遵循CLS / CLR的規則,所有語言的整個平台,如VB,C#,F3等。它是CLS / CLR定義如何查找方法,如何解決重載候選,等等。 而且,遺憾的是,重載超出泛型類型參數約束,它不包含在規范中。 IIRC將其添加到規范中會在整個平台上產生幾個問題(IIRC,類型和方法解析性能),所以沒有添加..但這就是我記得的。 重要的是,它不在語言和運行時平台規范中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM