试试 IEnumerable 的 10 个小例子

IEnumerable 接口是 C# 开发过程中非常重要的接口,对于其特性和用法的了解是十分必要的。本文将通过10个小例子,来熟悉一下其简单的用法。

全是源码

以下便是这10个小例子,响应的说明均标记在注释中。

每个以 TXX 开头命名的均是一个示例。建议从上往下阅读。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;
using Xunit.Abstractions;

namespace Try_More_On_IEnumerable
{
    public class EnumerableTests
    {
        private readonly ITestOutputHelper _testOutputHelper;

        public EnumerableTests(
            ITestOutputHelper testOutputHelper)
        {
            _testOutputHelper = testOutputHelper;
        }

        [Fact]
        public void T01普通的循环获取偶数()
        {
            // 创建一个集合存放最终结果
            var result = new List<int>();
            for (var i = 0; i <= 10; i++)
            {
                // 如果是偶数的话,将数字放入集合中
                if (i % 2 == 0)
                {
                    result.Add(i);
                }
            }

            // 断言最终的结果
            result.Should().Equal(0, 2, 4, 6, 8, 10);
        }

        [Fact]
        public void T02普通Enumerable()
        {
            // 通过静态方法获取偶数的Enumerable对象
            var result = GetNumber(10);

            // 断言结果
            result.Should().Equal(0, 2, 4, 6, 8, 10);

            /**
             * 这种写法比起 T01 的写法少了一个集合的创建,通常来说是性能更佳的写法
             */
        }

        /// <summary>
        /// 获取小于等于max的偶数
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        private static IEnumerable<int> GetNumber(int max)
        {
            for (var i = 0; i <= max; i++)
            {
                if (i % 2 == 0)
                {
                    // 使用 yield return 返回每次迭代的结果
                    yield return i;
                }
            }
        }

        [Fact]
        public void T02本地函数()
        {
            // 通过本地函数获取结果
            var result = GetNumber(10);

            // 断言结果
            result.Should().Equal(0, 2, 4, 6, 8, 10);

            /**
             * 使用本地函数获取 Enumerable 对象。
             * 此处的效果和静态方法类似。
             * 本地函数是 C# 7.0 才开始支持的语法特性。
             * 关于本地函数详细内容可以参见:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/local-functions
             */
            IEnumerable<int> GetNumber(int max)
            {
                for (var i = 0; i <= max; i++)
                {
                    if (i % 2 == 0)
                    {
                        yield return i;
                    }
                }
            }
        }

        [Fact]
        public void T03分离条件()
        {
            /**
             * 使用 Where 过滤结果
             * 这样的做法分离了“自增”逻辑和“判断是偶数”的逻辑
             */
            var result = GetNumber(10)
                .Where(x => x % 2 == 0);

            result.Should().Equal(0, 2, 4, 6, 8, 10);

            // 迭代时只是进行了自增操作
            IEnumerable<int> GetNumber(int max)
            {
                for (var i = 0; i <= max; i++)
                {
                    yield return i;
                }
            }
        }

        [Fact]
        public void T04Linq产生数值()
        {
            // 系统内置了一个方法来获取数字的自增序列,因此可以如此简化
            var result = Enumerable
                .Range(0, 11)
                .Where(x => x % 2 == 0);

            result.Should().Equal(0, 2, 4, 6, 8, 10);
        }

        [Fact]
        public void T05输出233()
        {
            // 输出3个数字 233
            var result = Get233().Take(3);
            result.Should().Equal(2, 3, 3);

            // 输出5个数字 23333
            result = Get233().Take(5);
            result.Should().Equal(2, 3, 3, 3, 3);

            IEnumerable<int> Get233()
            {
                // 第一次输出 2
                yield return 2;
                while (true)
                {
                    // 后面都输出 3
                    yield return 3;
                }
            }

            /**
             * 值得注意的是 while(true) 并不会导致程序陷入死循环
             * 因为 yield return 是采用按需供给的方式执行的。
             * 关于这点可以参考右侧文章:https://www.cnblogs.com/SilentCode/p/5014068.html
             */
        }

        [Fact]
        public void T06获取10个小于50的随机数()
        {
            /**
             * 过滤随机数中小于50的数字,只获取其中10个结果
             */
            var result = GetRandom()
                .Where(x => x < 50)
                .Take(10)
                .ToArray();

            // 断言
            result.Should().HaveCount(10);
            result.All(x => x < 50).Should().BeTrue();

            IEnumerable<int> GetRandom()
            {
                var random = new Random();
                // 不断输出 0-100 的随机数
                while (true)
                {
                    yield return random.Next(0, 100);
                }
            }
        }

        [Fact]
        public void T07自动补足随机数()
        {
            // 获取3个数字
            var result1 = GetData().Take(3);

            // 3 个数字分别为 0,1,2
            result1.Should().Equal(0, 1, 2);

            // 获取 10 个数字
            var result2 = GetData().Take(10).ToArray();

            // 前 5 个数字分别为 0,1,2,3,4
            result2.Take(5).Should().Equal(0, 1, 2, 3, 4);
            // 从第 5 个开始的数字都大于 10
            result2.Skip(5).Take(5).Should().Match(x => x.All(a => a > 10));

            /**
             * 获取一组数据,前5个数字是 0,1,2,3,4 。后面继续获取则为随机数
             */
            IEnumerable<int> GetData()
            {
                var staticData = new[] {0, 1, 2, 3, 4};
                foreach (var i in staticData)
                {
                    yield return i;
                }

                var random = new Random();
                // 不断输出 10-100 的随机数
                while (true)
                {
                    yield return random.Next(10, 100);
                }
            }
        }

        [Fact]
        public void T08条件转循环()
        {
            var book1 = GetReadingBook(DateTime.Parse("2019-08-30")).First();
            book1.Should().Be("每个周五都是快乐的一天");

            var book2 = GetReadingBook(DateTime.Parse("2016-02-29")).First();
            book2.Should().Be("四年一次的邂逅");

            var book3 = GetReadingBook(DateTime.Parse("2019-09-01")).First();
            book3.Should().BeSameAs("月老板软件开发小妙招三十二则");

            // 获取给定时间需要阅读的书籍名称
            IEnumerable<string> GetReadingBook(DateTime time)
            {
                // 周五
                if (time.DayOfWeek == DayOfWeek.Friday)
                {
                    yield return "每个周五都是快乐的一天";
                }

                // 2月29日
                if (time.Date.Month == 2 && time.Date.Day == 29)
                {
                    yield return "四年一次的邂逅";
                }

                // 其他时间阅读名著
                yield return "月老板软件开发小妙招三十二则";
            }
        }

        [Fact]
        public void T09获取一个链接字符串()
        {
            // 获取一个当前可用的链接字符串
            var conn = GetConnectionString().FirstOrDefault();
            conn.Should().Be("Source=赛博坦;UID=月x;Password=******");

            IEnumerable<string> GetConnectionString()
            {
                // 从一个文件中获取链接字符串
                var connFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "conn.txt");
                if (File.Exists(connFilename))
                {
                    var fileContent = File.ReadAllText(connFilename);
                    yield return fileContent;
                }

                // 从配置文件中读取链接字符串
                var dbConnectionString = ConfigurationManager.ConnectionStrings["db"]?.ConnectionString;
                if (!string.IsNullOrEmpty(dbConnectionString))
                {
                    yield return dbConnectionString;
                }

                // 返回默认的字符串
                yield return "Source=赛博坦;UID=月x;Password=******";
            }
        }

        [Fact]
        public async Task T10测试网络连接()
        {
            var httpClient = new HttpClient();
            try
            {
                await Task.WhenAll(SendRequests());
                _testOutputHelper.WriteLine("当前网络连接正常");
            }
            catch (Exception e)
            {
                _testOutputHelper.WriteLine("当前网络不正常,请检查网络连接");
            }

            IEnumerable<Task> SendRequests()
            {
                yield return Task.Run(() => httpClient.GetAsync("http://www.baidu.com"));
                yield return Task.Run(() => httpClient.GetAsync("http://www.bing.com"));
                yield return Task.Run(() => httpClient.GetAsync("http://www.taobao.com"));
            }
        }
    }
}

  

源码说明

以上示例的源代码放置于博客示例代码库中。

项目采用 netcore 2.2 作为目标框架,因此需要安装 netcore 2.2 SDK 才能运行。

原文地址:https://www.cnblogs.com/newbe36524/p/11442064.html

时间: 2024-11-09 04:42:21

试试 IEnumerable 的 10 个小例子的相关文章

Runtime的几个小例子(含Demo)

一.什么是runtime(也就是所谓的"运行时",因为是在运行时实现的.)           1.runtime是一套底层的c语言API(包括很多强大实用的c语言类型,c语言函数);  [runtime运行系统]           2.实际上,平时我们编写的oc代码,底层都是基于runtime实现的;                             [OC语言的动态性]  运行时系统 (runtime system),对于C语言,函数的调用在编译的时候会决定调用哪个函数.对

JS模拟键盘事件 -- 原理及小例子

小例子: (Chrome下可用,其他浏览器未测试,使用新方法,暂不考虑兼容性) 代码如下: 1 <input type="button" tabindex="-1" value="点点点点点" id="btn"> 2 <input type="text" placeholder="1"> 3 <input type="text" plac

python2.7练习小例子(十)

    10):古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?     程序分析:兔子的规律为数列1,1,2,3,5,8,13,21....     程序源代码: #!/usr/bin/python # -*- coding: UTF-8 -*- f1 = 1 f2 = 1 for i in range(1,22): print '%12ld %12ld' % (f1,f2), if (i % 3)

简述人脸特异性识别&amp;&amp;一个基于LBP和SVM的人脸识别小例子

原谅我用图片,MAC在Safari里给文章进行图文排版太麻烦啦~ 本文适合初入计算机视觉和模式识别方向的同学们观看~ 文章写得匆忙,加上博主所知甚少,有不妥和勘误请指出并多多包涵. 本文Demo的代码由HZK编写,特征点由月神和YK选择和训练. 转载请注明 copyleft by sciencefans, 2014 为了方便大家学习,附上高维LBP的核心代码 1 ################################################### 2 # 3 # 4 # NO

COM2 --- 小例子

在COM1 的小例子中,,我们大概知道什么是组件类 ,什么是接口了.这小节呢,我们来实现一下由一个组件类去实现两个接口的过程. 新建项目: 我们的 解决方案的 名字是 ComDemoCode ,项目名字是 MathToolKit  这表示 我们的 项目 自动 生成的 DLL  的名字就是 MathToolKit(数学工具包). 我们的继承关系 有必要 给大家 先 列出来,让大家 看看 在这里面,IPrimerMath接口 提供 + - * / % 五个基本运算方法,IAdvanceMath接口提

python try小例子

#!/usr/bin/python import telnetlib import socket try: tn=telnetlib.Telnet('10.67.21.29',60000) except socket.error, e: print e exit(1) tn.set_debuglevel(1) tn.write('quit'+'\n') print 'ok' socket.error为错误类型 e为对象 python try小例子,布布扣,bubuko.com

Go语言使用Protocol Buffer的小例子

Protocol Buffer与Golang出自同门.Golang对其的支持包在https://github.com/golang/protobuf 下. 弄个小例子. 1. 创建proto文件usermsg.proto  package pfmsg; option java_package = "com.example.pfmsg"; option java_outer_classname = "UserMessage"; enum UserStatus { OF

angular ngRoute小例子

ngRoute学习小例子 单页面应用中可以使用ng-view,当修改ng-view的template时可以实现一个页面html中展示不同内容(div部分). 例如index.html中包含ng-view 1 <!DOCTYPE HTML> 2 <html ng-app="app"> 3 <head> 4 <script src="./bower_components/angular/angular.js"></s

node.js安装及小例子

1.node.js安装:http://www.nodejs.org/download/ 下载msi版本,直接双击安装,默认在c盘programfiles下,可以进行配置. 2.在某路径下建立test.js文件(本人在D:\nod目录下): 代码: 1 var http = require('http'); 2 http.createServer(function (req, res) { 3 res.writeHead(200, {'Content-Type': 'text/plain'});