【IEnumerable】扩展方法的使用 C#

   直接进入主题吧...


       IEnumerable : 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。 好吧,迭代,我就理解成循环,这些名词真晦涩,没意思
       今天看的是 Using Extension Methods ,使用"扩展方法"。俺都开始看英文文档了,得瑟中...
       所谓扩展方法,是对类型的扩展。如对string扩展一个GotoHell(); 方法,可以这样用  “damn”.GotoHell();
       如何实现呢,咱创建一个新的类,叫做StringExtend,有这样一个方法,
        public static string GotoHell(this string str)
        {
             return str+"GotoHell";
         }
        然后在另一处调用(同一个命名空间哦),"Damn ".GotoHell();  输出的值为:“Damn GotoHell” (由此看出,我心情却是不好啊)

        这是一般类型的扩展方法,似乎与主题那不搭边呢,好吧,我跑题了。
        IEnumerable 我也不管他是什么东西,反正就理解像是一个列表的东西。而实际上List是继承的IEnumerable。
        为了使程序更形象,于是俺创建一个实体类:
        public class Product
       {
          public string Name { get; set; }
          public string Category { get; set; }
          public decimal Price { get; set; }
      }
      这儿又得跳跃一下,Using Automatically Implemented Properties。也就是public string Name{get;set;} 对应的英文定义了。
      翻译为:自动实现的属性。为啥叫自动实现的属性,都实现了哪些呢? 如果不这样写,那就需要这样:
      get{ return name; } // 这里还需要创建一个name变量
      set{ name=value;}
      确实比较繁琐,耦合性也稍微高一些,同时效率也稍微低一些。
      【Tag1】现在我们来点数据:
      IEnumerable<Product> products = new List<Product> {
            new Product{Name="one",Category="rose",Price=56},
            new Product{Name="two",Category="jack",Price=55},
            new Product{Name="three",Category="jack",Price=54}
            };
       上面说过了,IEnum... 就像是个列表的东西,List 实现了它,这样赋值不足为过吧。
       那现在我要筛选出 Category 为jack 的数据,怎么办呢。咱新建一个List temp ? 对吧,怕啥啊,不就浪费点内存吗,咱有的是。
       好吧,我以前就是这么想的,而如今,我觉得那样做,太TM操蛋了。
      ----------------------
       我新建一个类:MyextendClass
       public static IEnumerable<Product> FilterByCategory(this IEnumerable<Product> productEnum,string categoryParam)
       {
              foreach(Product pro in productEnum)   // 这里我习惯性写成 foreach(var item in productEnum)
              {
                  if(pro.Category==categoryParam)
                  {
                      yield return pro;  // yield 是什么鸟玩意儿啊? 我只知道他用在迭代器里面,告诉他这里结束了,下次你来迭代的时候往下一个迭代走。同时呢,他发现一个东西就立即返回过去,不要等待集合装入完毕,据说效 率杠杠滴哦。这是我的理解,有大虾的话,请留言更正。
                   }
               }
       }
      然后,就调用了:products.FilterByCategory("jack"); 好了,这样就获取了 category 为 jack 的列表,你想怎么处理输出都是你的事情了。
     再想想,如果我要计算jack分类的Price的总和呢?如果N多地方出现这种情况,难道我们都要重新写方法吗?话说,就算写好了,以后也不好维护呢。好吧,咱再扩展一个呗:
public static decimal TotalPrice(this IEnumerable<Product> productEnum)
{
    decimal total=0;
    foreach(var item in productEnum)
    {
         total+=item.Price;
     }
     return total;
}
Wonderful,这样我们就这样调用:products.FilterByCategory("jack").TotalPrice(); 是不是很方便,以后要修改这部分代码页相当方便。
只要一处扩展这个方法,到处都可以用。维护固然就很方便了。

有这么一种情况,我想按某种方式过滤出数据,可是我现在还不知道要怎么过滤。我需要把这一层写好先。然后有时间我再去独立的思考那一方面的逻辑。委托? 我给你参数和我需要的返回值类型,之后你要干嘛干嘛去,我不管了(这不就是汉语中委托的意思么,呵呵)。
这里有这样一个委托: Func<in T,out TResult> 给个T的参数,返回TResult 类型的值(话说对 泛型 了解的还不够深刻,不管乱解释,改天我再去瞅瞅)。
好了,写扩展方法咯:
public static IEnumerable<Product> Filter(this IEnumerable<product> productEnum,Func<Product,bool> selectorParam)
{
    foreach(var item in productEnum){
         if(selectorParam(item)){
              yield return item;
          }
    }
}
那委托都干了点啥呢?我们调用前给他赋予它的使命:
Func<Product,bool> categoryfilter=delegate(Product pro){  reutrn pro.Category=="rose";  };
products.Filter(categoryfilter); //终于得到rose了。
有没有一种方式,再简化下这种委托呢?有的,Lamada (这个我也不是很熟,改天一并看了吧):
Func<Product,bool> categoryfilter=pro=>pro.Category=="rose";
(好吧,关于扩展方法我就看了这么些,输出结果为 两个 “jack” ,一个 “rose” . 这男女比例真的失衡了,这咋分啊。    )

最后提一句,在【Tag1】的时候,IEnumerable 也可以写成 IList 或 其他类似的 继承了 IEnumerable 的类型或接口。

通过使用 IEnumerable 可以定制适合自己开发过程中的基本逻辑,就像PS中录制动作一般,相当使用。

又如一个例子:假设在B2C站中,商品详情页有商品评论,商品评论已经缓存了下来(我想这是必要的)。

        在显示评价时,有这样的需求,如果是置顶的则排在最前面,其次是精华评论,再者就是其他。

        方案a.我们可以使用正常的逻辑去处理,整出几十行代码。如果在其他使用类似的逻辑,只是过滤条件变了,我们又得重新写这部分的逻辑。

        方案b.如果我们新建一个扩展类,将这部分逻辑添加到扩展中。只需业务逻辑中添加几行代码便可实现需求。不仅从代码的美观上还是在系统的维护上都有很大的好处。
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IList<RefModel> list = Init();
            IList<RefModel> list2 = list.Filter_Attr(r => r.IsTop == true && r.Sex == "boy").ToList();
            Console.WriteLine("-------------------过滤-----------------------");
            foreach (var item in list2)
            {
                Console.WriteLine(item.Name + "  " + (item.IsTop ? "[T]  " : "") + (item.IsElite ? "[E]  " : "") + "[" + item.Sex + "]");
            }
            Console.WriteLine("-------------------重组:原顺序---------------------------");
            foreach (var item in list)
            {
                Console.WriteLine(item.Name + "  " + (item.IsTop ? "[T]  " : "") + (item.IsElite ? "[E]  " : ""));
            }
            Console.WriteLine("-------------------重组:规则排序后----------------------------");
            list = list.Filter_Order().ToList();
            foreach (var item in list)
            {
                Console.WriteLine(item.Name + "  " + (item.IsTop ? "[T]  " : "") + (item.IsElite ? "[E]  " : ""));
            }
            Console.ReadLine();
        }

        private static IList<RefModel> Init()
        {
            IList<RefModel> list = new List<RefModel>(){
                new RefModel { Name = "charles", Sex = "boy", IsTop = true, IsElite = true },
                new RefModel { Name = "charles1", Sex = "girl", IsTop = true, IsElite = false },
                new RefModel { Name = "charles2", Sex = "girl", IsTop = false, IsElite = true },
                new RefModel { Name = "charles3", Sex = "boy", IsTop = false, IsElite = true },
                new RefModel { Name = "charles4", Sex = "girl", IsTop = true, IsElite = false },
                new RefModel { Name = "charles5", Sex = "girl", IsTop = false, IsElite = true },
                new RefModel { Name = "charles6", Sex = "boy", IsTop = true, IsElite = true },
                new RefModel { Name = "charles7", Sex = "girl", IsTop = true, IsElite = false },
                new RefModel { Name = "charles8", Sex = "boy", IsTop = false, IsElite = false },
                new RefModel { Name = "charles9", Sex = "girl", IsTop = true, IsElite = true },
                new RefModel { Name = "charles10", Sex = "boy", IsTop = false, IsElite = false },
                new RefModel { Name = "charles11", Sex = "boy", IsTop = false, IsElite = false },
                new RefModel { Name = "charles12", Sex = "girl", IsTop = true, IsElite = true },
                new RefModel { Name = "charles13", Sex = "boy", IsTop = false, IsElite = false },
                new RefModel { Name = "charles14", Sex = "boy", IsTop = false, IsElite = true },
                new RefModel { Name = "charles15", Sex = "girl", IsTop = true, IsElite = true },
                new RefModel { Name = "charles16", Sex = "girl", IsTop = false, IsElite = false },
                new RefModel { Name = "charles17", Sex = "boy", IsTop = true, IsElite = true },
                new RefModel { Name = "charles18", Sex = "boy", IsTop = false, IsElite = true },
                new RefModel { Name = "charles19", Sex = "girl", IsTop = true, IsElite = true },
                new RefModel { Name = "charles20", Sex = "boy", IsTop = true, IsElite = true },
                new RefModel { Name = "charles21", Sex = "boy", IsTop = false, IsElite = false },
                new RefModel { Name = "charles22", Sex = "girl", IsTop = true, IsElite = true },
                new RefModel { Name = "charles23", Sex = "boy", IsTop = true, IsElite = false },
                new RefModel { Name = "charles24", Sex = "boy", IsTop = true, IsElite = true }};
            return list;
        }
    }

    public class RefModel
    {
        public string Name { get; set; }
        public string Sex { get; set; }
        public bool IsTop { get; set; }
        public bool IsElite { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace ConsoleTest
{public static class Filter{public static IEnumerable<RefModel> Filter_Attr(this IEnumerable<RefModel> list, Func<RefModel, bool> selectorParam){foreach (var item in list){if (selectorParam(item)){yield return item;}}}public static IEnumerable<RefModel> Filter_Order(this IEnumerable<RefModel> list){IList<RefModel> topList = new List<RefModel>();IList<RefModel> eliteList = new List<RefModel>();IList<RefModel> elseList = new List<RefModel>();foreach (var item in list){if (item.IsTop){topList.Add(item);//yield return item;//Tag FX 
                }else if (item.IsElite){eliteList.Add(item);}else{elseList.Add(item);}}///Tag X Start
            foreach (var item in topList){yield return item;}///Tag X End
            foreach (var item in eliteList){yield return item;}foreach (var item in elseList){yield return item;}}}
}

运行结果:(部分)

    最后如果理解 yield 的用法,那么可以将上述代码中 Tag X 行取消注释,并将 Tag X Start 内的代码注释掉,将得到相同的结果。这样讲减少一层循环。虽然效率提高的微乎其微,但却如我博客Header所述:不积跬步无以至千里。

       

    如对你有帮助,轻轻地东东手指,Recomend Or Comment 。 你的支持是我的不断前行的动力。                             欢迎转载。

转载于:https://www.cnblogs.com/shenchaoming/archive/2013/03/25/IEnumerable.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/474587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java的制造商,国内某通信设备制造商JavaEE开发岗面试题

1 EJB中有几种Bean&#xff0c;叙述有状态Bean和无状态Bean的区别。答&#xff1a;EJB中有Session Bean&#xff0c;Entity Bean&#xff0c;以及 Message Driven Bean。这两种的 Session Bean都可以将系统逻辑放在 method之中执行&#xff0c;不同的是 Stateful Session Bean …

LeetCode MySQL 571. 给定数字的频率查询中位数

文章目录1. 题目2. 解题1. 题目 Numbers 表保存数字的值及其频率。 ----------------------- | Number | Frequency | -----------------------| | 0 | 7 | | 1 | 1 | | 2 | 3 | | 3 | 1 | -------…

Java中文乱码处理

出现的情况&#xff1a; 表单FORM、POST、GET、超链接、sendRedirect() 解决方法&#xff1a; 如果是POST使用 HttpRequest.setCharacterEncoding("utf-8"); 如果是GET使用 String unew String( req.getParameter("username") .getBytes("iso-8859-1…

mysql 混合模式,SQLServer2005混合模式登录配置(用户登录错误18452,233,4064)

一、错误提示&#xff1a;用户登录失败,该用户与可信SQL Server连接无关联 错误18452原因是远程登录没配置好&#xff0c;配置方法如下&#xff1a;1&#xff1a;开启SQL2005远程连接功能配置工具->SQLServer外围应用配置器->服务和连接的外围应用配置器->打开SQLEXPR…

LeetCode 632. 最小区间(排序+滑动窗口)

文章目录1. 题目2. 解题1. 题目 你有 k 个升序排列的整数数组。 找到一个最小区间&#xff0c;使得 k 个列表中的每个列表至少有一个数包含在其中。 我们定义如果 b-a < d-c 或者在 b-a d-c 时 a < c&#xff0c;则区间 [a,b] 比 [c,d] 小。 示例 1: 输入:[[4,10,15,…

ubuntu安装操作HttpSQS高速队列

HTTPSQS安装 ulimit -SHn 65535wget http://httpsqs.googlecode.com/files/libevent-2.0.12-stable.tar.gztar zxvf libevent-2.0.12-stable.tar.gzcd libevent-2.0.12-stable/./configure --prefix/usr/local/libevent-2.0.12-stable/makemake installcd ../wget http://https…

dz论坛php.ini设置,Discuz!X1.5至3.2论坛Win主机与Linux主机伪静态设置方法

用discuz x1.5至3.2的程序搭建的一个论坛&#xff0c;DZ论坛win主机与linux主机伪静态规则的设置方法&#xff01;Windows主机设置方法&#xff1a;1.建立一个名为 httpd.ini 的文件&#xff0c;可以先在电脑上面新建一个文本&#xff0c;然后将下面的这些代码复制到本文里面&a…

LeetCode MySQL 1194. 锦标赛优胜者

文章目录1. 题目2. 解题1. 题目 Players 玩家表 -------------------- | Column Name | Type | -------------------- | player_id | int | | group_id | int | -------------------- 玩家 ID 是此表的主键。 此表的每一行表示每个玩家的组。Matches 赛事表 -----…

[解题报告]HDU 1249 三角形

三角形 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3238 Accepted Submission(s): 2224 Problem Description用N个三角形最多可以把平面分成几个区域?Input输入数据的第一行是一个正整数T(1<T<10000…

php 管理员表和用户表,求discuz的管理员数据表和用户数据表结构

magicmaster07-23 09:35等级3楼不想装mysql&#xff0c;PHP&#xff0c;还有那种phpadmin只要了解一下用户表结构&#xff0c;用注入删掉一个版主&#xff0c;呵呵discuz是怎么把数据表转成向量的?52juanjuan07-23 09:46等级4楼你可以把它的系统与现在运行的网址给各位去说说。…

LeetCode MySQL 1097. 游戏玩法分析 V

文章目录1. 题目2. 解题1. 题目 Activity 活动记录表 ----------------------- | Column Name | Type | ----------------------- | player_id | int | | device_id | int | | event_date | date | | games_played | int | ---------------------…

PCA主成分分析

首先可以先阅读这一篇文档。 http://wenku.baidu.com/view/4df2c1d276a20029bd642d76.html 基本的算法和原理在上面的文档内已经写得很详细了&#xff0c;总结一下PCA的数学模型吧&#xff1a; 第一种求法&#xff1a; 易知A是对称阵&#xff0c;所以可以对角化 因为P是要求出来…

oracle xe 最大连接数,解决Oracle XE报错ORA-12516(Oracle回话数超出限制)

本地安装的OracleXEUniv—oracle特别版&#xff0c;免费用户可以自由使用&#xff0c;但有连接数量和存储限制。最近遇到一个问题&#xff0c;当我的SSM项目连接本地数据库oracleXE后&#xff0c;我的navicat再连接时就会报错ORA-12516&#xff0c;就是oracle的会话数超出了限制…

LeetCode MySQL 579. 查询员工的累计薪水(over(rows n preceding)选取窗口1+前n条)

文章目录1. 题目2. 解题1. 题目 Employee 表保存了一年内的薪水信息。 请你编写 SQL 语句&#xff0c;对于每个员工&#xff0c;查询他除最近一个月&#xff08;即最大月&#xff09;之外&#xff0c;剩下每个月的近三个月的累计薪水&#xff08;不足三个月也要计算&#xff…

二元查找树的后序遍历结果

题目&#xff1a;输入一个整数数组&#xff0c;判断该数组是不是某二元查找树的后序遍历的结果。如果是返回 true &#xff0c;否则返回 false 。 例如输入5、7、6、9、11、10、8&#xff0c;由于这一整数序列是如下树的后序遍历结果&#xff1a; 8 / \ 6 10 …

oracle收集直方图,sql – 在Oracle中创建直方图/频率分布的最佳方法?

如果您的创建时间是日期列,那么这将是微不足道的&#xff1a;SELECT TO_CHAR(CREATE_TIME,DAY:HH24),COUNT(*)FROM EVENTSGROUP BY TO_CHAR(CREATE_TIME,DAY:HH24);实际上,转换createtime列并不太难&#xff1a;select TO_CHAR(TO_DATE(19700101,YYYYMMDD) createtime / 86400…

LeetCode MySQL 615. 平均工资:部门与公司比较(over窗口函数)

文章目录1. 题目2. 解题1. 题目 给如下两个表&#xff0c;写一个查询语句&#xff0c;求出在每一个工资发放日&#xff0c;每个部门的平均工资与公司的平均工资的比较结果 &#xff08;高 / 低 / 相同&#xff09;。 表&#xff1a; salary | id | employee_id | amount | p…

oracle加密可以跟java一致吗,在GBase 8s上使用java udr实现Oracle兼容的加密解密功能...

最近碰到客户从Oracle迁移到GBase 8s使用到字段加密解密功能,使用到了Utl_raw.cast_to_varchar2、Utl_raw.cast_to_raw、Utl_encode.base64_decode、dbms_obfuscation_toolkit.desdecrypt等oracle特有函数,这些与GBase 8s自带的加密函数DECRYPT_CHAR并不兼容。客户暂时只能考虑…

LeetCode MySQL 1127. 用户购买平台 *

文章目录1. 题目2. 解题1. 题目 支出表: Spending ---------------------- | Column Name | Type | ---------------------- | user_id | int | | spend_date | date | | platform | enum | | amount | int | ---------------------- 这张表记…

生活中常见的操作系统

一、 操作系统 1.1 操作系统概念 操作系统&#xff08;Operating System&#xff0c;简称 OS&#xff09;是管理和控制计算机硬件与软件资源的计算机程序&#xff0c;是直接运行在“裸机”上的最基本的系统软件&#xff0c;任何其他软件都必须在操作系统的支持下才能运行。 操…