设为首页 加入收藏

TOP

【C#夯实】我与接口二三事:IEnumerable、IQueryable 与 LINQ(二)
2019-09-17 18:23:52 】 浏览:76
Tags:夯实 我与 接口 二三 IEnumerable IQueryable LINQ
teLine($
"{Padding} About to yield {i}"); yield return i; WriteLine($"{Padding} After yield"); } WriteLine($"{Padding} Yielding final value"); yield return -1; WriteLine($"{Padding} End of CreateEnumerable"); } }

 

  此处可以留意“After yield”是什么时候出现的,就会发现[1]:

   l   在第一次调用MoveNext之前,CreateEnumerable中的代码不会被调用;

   l   当调用MoveNext时,Current也同时变化;

   l   在yield return的位置,代码就停止执行,在下一次调用MoveNext时又继续执行(再return一次)

  yield的故事还没有完,此处就简短介绍。

 

  yield return提供了逐个返回的条件,对于仅是取集合当中符合筛选条件的一项,用yield是方便的,逐个返回的情况下,不会占用过多的存储空间。但如果涉及到排序(或者比大小、最值)的问题,那必然要求集合当中的所有数据处于可用状态,这里也出现了一些传值的概念。

  yield return属于延迟执行(Deferred Execution),延迟执行再区分为惰性求值(Lazy eva luation)和热情求值(Eager eva luation)。 

Deferred but eager execution

Deferred and lazy execution

    IEnumerable<int> GetComputation(int maxIndex)

    {

        var result = new int[maxIndex];

        for(int i = 0; i < maxIndex; i++)

        {

            result[i] = Computation(i);

        }

        foreach(var value in result)

        {

            yield return value;

        }

    }

    IEnumerable<int> GetComputation(int maxIndex)

    {

        for(int i = 0; i < maxIndex; i++)

        {

            yield return Computation(i);

        }

    }

  详见:https://stackoverflow.com/questions/2515796/deferred-execution-and-eager-eva luation

 

  下面这个例子,是惰性求值,迭代器返回的值受lambda表达式控制,并且是在每一次访问到这一个“点”的时候,再去返回 “点”的处理结果。热情求值是直接返回“点”,没有再过处理。两相比较,还得看具体的编程情况以作选择,此处不赘述。

    static void Main(string[] args)
    {
        var sequence = Generate(10, () => DateTime.Now);
        foreach (var value in sequence)
            WriteLine($"{value:T}");
    }

    static IEnumerable<TResult> Generate<TResult>(int number, Func<TResult> generator)
    {
        for (var i = 0; i < number; i++)
        {
            Sleep(400);
            yield return generator();
        }
    }

   (为了逻辑上的全面性,)与延迟执行相对的是立即执行(Immediately Execution),是一次返回就完成函数的操作。

 

二、迭代器 IQueryable

  LINQ to Object 是针对本地数据存储(local data store)来执行查询的,系统会根据lambda表达式里面的逻辑创建匿名的委托,并执行代码;

  LINQ to SQL 针对的是在数据库执行的,会把查询条件解析成T-SQL,并且把SQL语句发送给数据库引擎。

 

  关于,自动生成SQL语句这一点,可以做个尝试,例如:创建了一个EF,调试监控连接数据库后返回的变量类型。

    var dbcontext = new CM_FORTESTEntities();
    var tb1 = dbcontext.tblEmployees;
    var tb2 = dbcontext.tblEmployees.Where(a => a.Id == 1);
    var tb3 = dbcontext.tblEmployees.Where(a => a.Gender == "Male").OrderByDescending(a => a.Id);

 

 

 

  咋一看,怎么还能是不同类型?但是再看类成员,会发现一些端倪:

public abstract class DbSet : DbQuery, IInternalSetAdapter
public abstract class DbQuery : IOrderedQueryable, IQueryable, IEnumerable, IListSource, IInternalQueryAdapter

public interface IOrderedQueryable : IQueryable, IEnumerable

 

  好了,终于引入到这个朋友——IQueryable,IQueryable有些什么必要实现的方法呢?

    public class QueryableSample : IQueryable
    {
        public Expression Expression => throw new NotImplementedException();
        public Type ElementType =
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ASP.NET+d3.js实现Sqlserver数据.. 下一篇新增筛选方案

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目