【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,一经查实,立即删除!

相关文章

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

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

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,…

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 赛事表 -----…

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…

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

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

LeetCode MySQL 1127. 用户购买平台 *

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

Example3_1

import java.util.*;public class Example3_1{ public static void main(String args[]){ Scanner readernew Scanner(System.in); System.out.println("输入待移位的int型整数:"); int xreader.nextInt(); System.out.println("输入移位量:"); int n…

oracle事务重要属性,Oracle中的事务(2)--属性和隔离级别

事务的属性1.只读属性(read only)只读事务&#xff0c;只执行查询操作&#xff0c;而不允许执行DML(增、删、改)操作&#xff0c;使用只读事务&#xff0c;可以让用户只取到某个时间点的数据。假如有一个机票代售点&#xff0c;有一个管理员想在一个时间点进行统计总共卖出去的…

edge.js架起node.js和.net互操作桥梁

今天要介绍的是edge.js这个github上刚兴起的开源项目&#xff0c;它可以让node.js和.net之间在in-process下互操作。.net版本在4.5及以上&#xff0c;因为.net4.5带来的Task&#xff0c;asyn&#xff0c;await关键字和node.js的Event模型正好匹配。如果你感兴趣的话&#xff0c…

LeetCode MySQL 180. 连续出现的数字(cast)

文章目录1. 题目2. 解题1. 题目 编写一个 SQL 查询&#xff0c;查找所有至少连续出现三次的数字。 --------- | Id | Num | --------- | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 1 | | 6 | 2 | | 7 | 2 | --------- 例如&#xff0c;给定上面的 L…

LeetCode MySQL 178. 分数排名(dense_rank连续排名)

文章目录1. 题目2. 解题1. 题目 编写一个 SQL 查询来实现分数排名。 如果两个分数相同&#xff0c;则两个分数排名&#xff08;Rank&#xff09;相同。 请注意&#xff0c;平分后的下一个名次应该是下一个连续的整数值。 换句话说&#xff0c;名次之间不应该有“间隔”。 --…

LeetCode MySQL 185. 部门工资前三高的所有员工(dense_rank)

文章目录1. 题目2. 解题1. 题目 Employee 表包含所有员工信息&#xff0c;每个员工有其对应的工号 Id&#xff0c;姓名 Name&#xff0c;工资 Salary 和部门编号 DepartmentId 。 --------------------------------- | Id | Name | Salary | DepartmentId | ---------------…

jquery非常不错的图片切换,多种切换效果

下载&#xff1a; http://files.cnblogs.com/timy/wowslider.rar转载于:https://www.cnblogs.com/timy/archive/2013/04/03/2998381.html

SQLSERVER字符串截取------STUFF

STUFF ( character_expression , start , length ,character_expression ) 参数 character_expression 一个字符数据表达式。character_expression 可以是常量、变量&#xff0c;也可以是字符列或二进制数据列。 start 一个整数值&#xff0c;指定删除和插入的开始位置。如…

LeetCode MySQL 601. 体育馆的人流量(row_number+over+cast)

文章目录1. 题目2. 解题1. 题目 X 市建了一个新的体育馆&#xff0c;每日人流量信息被记录在这三列信息中&#xff1a;序号 (id)、日期 (visit_date)、 人流量 (people)。 请编写一个查询语句&#xff0c;找出人流量的高峰期。高峰期时&#xff0c;至少连续三行记录中的人流量…