你如何知道一个集合将充当 IEnumerable 还是 IQueryable?

我有这行代码:

var attachments = EntityRepository<Attachment>().Entities
.Where(at => at.EntityType == EntityType.EmailTemplate)
.ToDictionary(at => at.Extension, at => at);

EntityRepository<Attachment>().EntitiesSystem.Data.Entity.Infrastructure.DbQuery<TResult>是同时实现IQueryable<TResult>和 的类型IEnumerable<TResult>

我如何确定它是否充当IEnumerable<T>(即从数据库中检索所有行,然后在 C# 中进行过滤)或充当IQueryable<T>(将 C# 谓词转换为 SQL 查询并仅检索这些行)。


郎朗坤
浏览 108回答 2
2回答

慕仙森

我想你可能对这个有一个小小的误解IEnumerable。它只是说该类支持迭代。它不会直接影响数据的获取方式。此外,IQueryable实现IEnumerable,因此所有IQueryable实例也是IEnumerable。这是有道理的,因为您可以迭代结果。在您的示例中,缺少这意味着IQueryable“从数据库检索所有行,然后在 C# 中进行过滤”。

绝地无双

LINQ 中有 2 个不同的扩展 - IEnumerable和IQueryable。当您编写EntityRepository<Attachment>().Entities .Where(at => at.EntityType == EntityType.EmailTemplate)编译器时,它会检查类型Entities,并声明“更具体”,IQueryable编译器会选择Queryable.Where()方法,并且表达式由IQueryProvider转换为 SQL。当您编写时,.ToDictionary(at => at.Extension, at => at)编译器找不到Queryable.ToDictionary(),因此它会回退到Enumerable.ToDictionary()内存中过滤项目。C# 语言规范中定义了扩展方法调用规则:候选方法集被简化为仅包含来自最派生类型的C.F方法:对于集合中的每个方法,其中C是声明该方法的类型F,所有在 的基类型中声明的方法都C将从集合中删除。此外,如果C是 以外的类类型object,则接口类型中声明的所有方法都将从集合中删除。(后一条规则仅在方法组是对具有除 object 之外的有效基类和非空有效接口集的类型参数进行成员查找的结果时才有效。) public interface IInterfaceA { }    public interface IInterfaceB : IInterfaceA { }    public static class MyExtensions {        public static void Print(this IInterfaceA a) => Console.WriteLine("A");        public static void Print(this IInterfaceB b) => Console.WriteLine("B");    }    public class AB: IInterfaceA, IInterfaceB { }    public class BA: IInterfaceB, IInterfaceA { }    public partial class Program    {        static void Main(string[] args)        {            new AB().Print(); // B            new BA().Print(); // B        }    }
打开App,查看更多内容
随时随地看视频慕课网APP