设为首页 加入收藏

TOP

【C#夯实】我与接口二三事:IEnumerable、IQueryable 与 LINQ(一)
2019-09-17 18:23:52 】 浏览:72
Tags:夯实 我与 接口 二三 IEnumerable IQueryable LINQ

  学生时期,有过小组作业,当时分工一人做那么两三个页面,然而在前端差不多的时候,我和另一个同学发生了争执。当时用的是简单的三层架构(DLL、BLL、UI),我个人觉得各写各的吧,到时候合并,而他觉得应该把底层先写好,他好直接调用中间层的方法。

  到出来工作之后,接触接口,想整理一下这个:接口到底是个什么概念呢?

  需要说明一点的是,我这里说的接口,不是API那个接口,而是“暂时没实现”那个接口。

  刚接触接口类型的时候,还不太熟练,看到返回接口类型的方法,总在奇怪,这个返回的对象怎么知道它取哪个实现?可以看一个简单的例子:

报错  

(无法创建抽象类或接口的实例  

    var test = new ITestInterface();

正确   

    ITestInterface infa = new TestInterface();

    infa.Func1();

  也即,返回的类型总是具类,是确定的,方法已经实现的

ITestInterface infa = new TestInterface();

   其中的 ITestInterface 更像一个模具,对应这个模具造型的内容,由TestInerface提供。

  那么,接口到底如何使用?

  接口的使用,要这样看:“具备某种特征(功能)”。

  例如看 ITestInterface infa = new TestInterface(); 其中,TestInterface具备有ITestInterface的特征,而ITestInterface作为有某种特征(功能)的标记,它对具体如何达到这种特征(功能)是不感兴趣的,有标记就有特征。这种标记的体现,在C#里面就是继承。

  说到这里,老朋友IEnumerable是一定要介绍的。

 

一、迭代器 IEnumerable

  集合这种数据结构是很常见的,通常的操作是对集合的内容做筛选,或排序。IEnumerable接口描述的是返回可循环访问集合的枚举数,继承这个接口,需要实现 public IEnumerator GetEnumerator() {} 方法。

  那么,IEnumerator是个什么er?继承这个接口之后,IDE提示需要实现的方法——

    public class Iterator : IEnumerator
    {
        public object Current => throw new NotImplementedException();
        public bool MoveNext()  { … }
        public void Reset()  { … }
    }

   有一个当前对象,一个是否能指向下一个的判断,还有一个重置。那么,可以想象迭代器应该是这样用的:

    Iterator iterator = new Iterator();
    while (iterator.MoveNext())
    {
        // Get iterator.Current to do something..
        Console.WriteLine(iterator.Current.ToString());
    }

  但这看起来,并不太聪明,或者这样使用比较“合理”:

 

  是不是get到了某种真相?foreach里面接受的是IEnumerable对象,并且会在此处调用到GetEnumerator去得到Enumerator。那么到底public IEnumerator GetEnumerator(){}要怎么实现呢,C# 2已经提供了yield语句简化迭代器。

    public class IterationSample : IEnumerable
    {
        public IEnumerator GetEnumerator()
        {
            for (int index = 0; index < values.Length; index++)
            {
                yield return values[(index + startingPoint) % values.Length];
            }
        }

        public object[] values;
        public int startingPoint;

        public IterationSample(object[] values, int startingPoint)
        {
            this.values = values;
            this.startingPoint = startingPoint;
        }
    }

   再来使用Enumerator:

    object[] objs = new object[]{"a", "b", "c", "d"};
    IterationSample sam = new IterationSample(objs, 0);
    foreach (var str in sam)
    {
        // do something..
    }

  可以想象,yield是个怎么样的存在,“一次一次返回”这是我对yield的第一印象描述。但总觉得还是有些说不清楚,这种时候还是得看看书:

  “yield return 语句指表示 ’暂时地’ 退出方法——事实上,可以把它当做暂停”,

  既然有这种说法,那还得给出个demo[1],关于怎么个“暂停”。

  (这里悄咪咪用C# 6的新语法using static System.Console; 实在懒得打 Console.WriteLine();)

    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<int> iterable = CreateEnumerable();
            IEnumerator<int> iterator = iterable.GetEnumerator();
            WriteLine("Starting to iterate");
            while (true)
            {
                WriteLine("Calling MoveNext()..");
                bool result = iterator.MoveNext();
                WriteLine($"MoveNext result = {result}");
                if (!result) break;
                WriteLine("Fetching Current..");
                WriteLine($"..Current result = {iterator.Current.ToString()}");
            }
            ReadLine();
        }

        static readonly string Padding = new string(' ', 30);
 
        static IEnumerable<int> CreateEnumerable()
        {
            WriteLine("Start of CreateEnumerable()");
            for (int i = 0; i < 2; i++)
            {
                Wri
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ASP.NET+d3.js实现Sqlserver数据.. 下一篇新增筛选方案

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目