C#语法糖之第六篇: 泛型委托- Predicate<T>、Func<T>

今天继续分享泛型委托的Predicate<T>,上篇文章讲了Action委托,这个比Action委托功不一样的地方就是委托引用方法是Bool返回值的方法,Action为无返回值。首先我们看一下它的定义吧:

1 public delegate  bool Predicate<T>(T obj);

从其定义可以看到,此委托引用一个返回bool 值的方法,在实际开发中,通常使用Predicate<T>委托变量引用一个“判断条件函数”,在判断条件函数内部书写代码表明函数参数所引用的对象应满足的条件,条件满足时,函数返回true.

我们在自己实现一下该委托:

 1 public static class PredicateClass
 2
 3     {
 4
 5         public delegate bool PanDuan<T>(T t);
 6
 7         public static List<T> MyFind<T>(this List<T> tList, PanDuan<T> find)
 8
 9         {
10
11             List<T> newTs = new List<T>();
12
13             foreach (T t in tList)
14
15             {
16
17                 if (find(t))
18
19                 {
20
21                     newTs.Add(t);
22
23                 }
24
25             }
26
27             return newTs;
28
29         }
30
31         public static bool 打印学生信息(Student stu)
32
33         {
34
35             if (stu.Age > 20) return true;
36
37             return false;
38
39         }
40
41         public static bool 打印教师信息(Teacher teacher)
42
43         {
44
45             if (teacher.Age > 40 && teacher.TeachNum=="001") return true;
46
47             return false;
48
49         }
50
51     }

调用代码如下:

 1  List<Student> students=new List<Student>();
 2
 3             students.Add(new Student{ StuNum = "001",StuName = "zhangsan",Age = 20});
 4
 5             students.Add(new Student { StuNum = "002", StuName = "lisi", Age = 21 });
 6
 7             students.Add(new Student { StuNum = "003", StuName = "wangwu", Age = 22 });
 8
 9             List<Teacher> teacher=new List<Teacher>();
10
11             teacher.Add(new Teacher{TeachNum = "004",TeachName = "teacher1",Age = 50});
12
13             teacher.Add(new Teacher { TeachNum = "005", TeachName = "teacher2", Age = 51 });
14
15             teacher.Add(new Teacher { TeachNum = "006", TeachName = "teacher3", Age = 52 });
16
17             Console.WriteLine("原始总数:"+teacher.Count);
18
19             List<Teacher> teachers=teacher.MyFind(PredicateClass.打印教师信息);
20
21             Console.WriteLine("过滤后总数:"+teachers.Count);
22
23             Console.WriteLine("原始总数:" + students.Count);
24
25             List<Student> studeList = students.MyFind(PredicateClass.打印学生信息);
26
27             Console.WriteLine("过滤后总数:" + studeList.Count);

输出效果:

以上效果可以看出通过自定义泛型委托来判断和过滤一些信息,最后得到过滤后的数据。

以上代码可以简化:

 1 //标准写法
 2
 3 Console.WriteLine("原始总数:" + teacher.Count);
 4
 5             List<Teacher> teachers = teacher.MyFind(
 6
 7                 new PredicateClass.PanDuan<Teacher>(delegate(Teacher t)
 8
 9                 {
10
11                     if (t.Age>21&&t.TeachNum=="001")
12
13                     {
14
15                         return true;
16
17                     }
18
19                     return false;
20
21                 }));
22
23             Console.WriteLine("过滤后总数:" + teachers.Count);
24
25 //匿名方法
26
27             Console.WriteLine("原始总数:" + teacher.Count);
28
29             List<Teacher> teachers1 = teacher.MyFind(
30
31                delegate(Teacher t)
32
33                 {
34
35                     if (t.Age > 21 && t.TeachNum == "001")
36
37                     {
38
39                         return true;
40
41                     }
42
43                     return false;
44
45                 });
46
47             Console.WriteLine("过滤后总数:" + teachers.Count);
48
49 //Lambda表达式
50
51             Console.WriteLine("原始总数:" + teacher.Count);
52
53             List<Teacher> teachers2 = teacher.MyFind(
54
55                u=>
56
57                {
58
59                    if (u.Age > 21 && u.TeachNum == "001")
60
61                    {
62
63                        return true;
64
65                    }
66
67                    return false;
68
69                });
70
71             Console.WriteLine("过滤后总数:" + teachers.Count);

输出结果:

从结果可以看出,这三个方法结果都是一样的。学生类的打印方法跟这个一样,所以在这里不做演示了,只要理解了这个方法以后在看看微软系统内置委托就很容易理解了,在这里用List的FindAll()方法吧:

 1 List<Student> students=new List<Student>();
 2
 3             students.Add(new Student{ StuNum = "001",StuName = "zhangsan",Age = 20});
 4
 5             students.Add(new Student { StuNum = "002", StuName = "lisi", Age = 21 });
 6
 7             students.Add(new Student { StuNum = "003", StuName = "wangwu", Age = 22 });
 8
 9             List<Teacher> teacher=new List<Teacher>();
10
11             teacher.Add(new Teacher{TeachNum = "004",TeachName = "teacher1",Age = 50});
12
13             teacher.Add(new Teacher { TeachNum = "005", TeachName = "teacher2", Age = 51 });
14
15             teacher.Add(new Teacher { TeachNum = "006", TeachName = "teacher3", Age = 52 });
16
17             Console.WriteLine("原始总数:"+teacher.Count);
18
19             List<Teacher> tt=teacher.FindAll(new Predicate<Teacher>(delegate(Teacher t)
20
21                 {
22
23                     if (t.TeachNum == "004") return true;
24
25                     return false;
26
27                 }));
28
29             Console.WriteLine("原始总数:"+tt.Count);

输出结果:

在分享一下Func<T>,个人觉得这个也是这三个中功能最强大的,我先看看微软官网的解释:

Func<T,TResut>:封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。

我们在上面的例子上在扩展,因为上面委托的方法返回值是bool类型,如果需要返回指定类型的话,上面的委托就不能满足要求了,所以用Func〈T〉很容易实现的,比如我们在上面的老师类中筛选年龄,组成一个新的集合:

具体代码如下:

1 List<int> AgeList=teacher.Select(new Func<Teacher, int>(delegate(Teacher t)
2
3                 {
4
5                     return t.Age;
6
7                 })).ToList();
8
9             AgeList.ForEach(u => { Console.WriteLine(u);});

输出结果:

以上结果可以看出来把老师的年龄打印出来了,具体写法应该不用再解释了吧,因为这个写法上面都不止一次的写了。我们在把匿名方法简化成Lambda表达式:

1 List<int> AgeList=teacher.Select(t=>
2
3                 {
4
5                     return t.Age;
6
7                 }).ToList();
8
9             AgeList.ForEach(u => { Console.WriteLine(u);});

我们在写一个返回自定义类型的例子:

把上面的例子在扩展为返回满足要求的老师集合:

 1 List<Student> students=new List<Student>();
 2
 3             students.Add(new Student{ StuNum = "001",StuName = "zhangsan",Age = 20});
 4
 5             students.Add(new Student { StuNum = "002", StuName = "lisi", Age = 21 });
 6
 7             students.Add(new Student { StuNum = "003", StuName = "wangwu", Age = 22 });
 8
 9             List<Teacher> teacher=new List<Teacher>();
10
11             teacher.Add(new Teacher{TeachNum = "004",TeachName = "teacher1",Age = 20});
12
13             teacher.Add(new Teacher { TeachNum = "005", TeachName = "teacher2", Age = 51 });
14
15             teacher.Add(new Teacher { TeachNum = "006", TeachName = "teacher3", Age = 52 });

 1 List<Student> tt = teacher.Select(
 2
 3                 new Func<Teacher, Student>(
 4
 5                     delegate(Teacher u)
 6
 7                         {
 8
 9                             Student e = new Student();
10
11                             if (u.Age < 23)
12
13                             {
14
15                                 e.StuName = u.TeachName;
16
17                                 e.Age = u.Age;
18
19                                 e.StuNum = u.TeachNum;
20
21                             }
22
23                             else
24
25                             {
26
27                                 return null;
28
29                             }
30
31                             return e;
32
33                         }
34
35                 )
36
37             ).ToList();
38
39             tt.ForEach(u =>
40
41                 {
42
43                     if (u != null) Console.WriteLine("姓名:"+u.StuName +"年龄:"+ u.Age);
44
45                 });

输出结果为:

这个就是年龄为小于23的老师赋值给学生类,并打印的例子,我在这里把逻辑写成匿名方法了,如朋友们觉得匿名方法有点乱,就可以把匿名方法分离到独立方法中:

 1 List<Student> tt = teacher.Select(
 2
 3                 GetStudentFromTeacher
 4
 5                 ).ToList();
 6
 7             tt.ForEach(u =>
 8
 9                 {
10
11                     if (u != null) Console.WriteLine("姓名:"+u.StuName +"年龄:"+ u.Age);
12
13                 });
14
15 public static Student GetStudentFromTeacher(Teacher u)
16
17         {
18
19             Student e = new Student();
20
21             if (u.Age < 23)
22
23             {
24
25                 e.StuName = u.TeachNum;
26
27                 e.Age = u.Age;
28
29                 e.StuNum =u.TeachNum;
30
31             }
32
33             else
34
35             {
36
37                 return null;
38
39             }
40
41             return e;
42
43         }

希望我的分享给大家带来帮助,也希望大家给出宝贵的意见,小弟也是刚写博客,所以很多地方的不是很专业,大白话为多,希望大家原谅!

原文来自我的个人网站:http://www.yaosutu.cn/archives/568

C#语法糖之第六篇: 泛型委托- Predicate<T>、Func<T>,布布扣,bubuko.com

时间: 2024-10-16 09:00:17

C#语法糖之第六篇: 泛型委托- Predicate<T>、Func<T>的相关文章

C#语法糖之第五篇: 泛型委托- Action&lt;T&gt;

因为工作的原因(其实还是个人的惰性)昨天没有给大家分享文章,然后这几天也有很多园友也提出了他们报告的意见及指导,再次感谢这些兄弟们的照顾我 和支持,这个分类的文章我当时想的是把我的学习经验和工作中用到的语法给大家分享给大家,希望能起到帮助的作用,但是本人也是个菜鸟,不是什么大神,所以 学习中也有不足的地方和没有扫到的地方,这里对上次扩展方法语法糖的问题,扩展方法确实是3.0开始就有了,或许是我以前没有用到,也没有查询欠缺,若要给大家带来不便,请大家原谅,现在把标题也修改为C#语法糖了,这里给大家

C#4.0语法糖之第五篇: 匿名类 &amp; 匿名方法

今天时间有点早,所以上来在写一篇文章吧,继续上一篇的文章,在我们平时编程过程中有没有遇到过这样的一个情景,你定义的类只是用来封装一些相关的数据,但并不需要相关联的方法.事件和其他自定义的功能.同时,这个类仅仅在当前的应用程序中使用,而不需要在项目间重用.你所需要的只是一个“临时的”类型,现在我们来看看这个传统类的定义: 1 internal class oneClass 2  3 { 4  5      //定义若干私有数据成员 6  7      //通过属性来封装每个数据成员 8  9   

C#4.0语法糖之第三篇: 参数默认值和命名参数 对象初始化器与集合初始化器

今天继续写上一篇文章C#4.0语法糖之第二篇,在开始今天的文章之前感谢各位园友的支持,通过昨天写的文章,今天有很多园友们也提出了文章中的一些不足,再次感谢这些关心我的园友,在以后些文章的过程中不断的完善以及自我提高,给各位园友们带来更好,更高效的文章. 废话就说到这里,下面正式进入我们的今天的C#4.0语法糖,今天给大家分享一下参数默认值.命名参数.对象初始化器和集合初始化器. 参数默认值和命名参数:方法的可选参数是.net 4.0最新提出的新的功能,对应简单的重载可以使用可选参数和命名参数混合

C#4.0语法糖之第四篇: 扩展方法

今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到这个知识点之前做的方法: 最笨的办法就是修改原来的类型,然后添加一个方法来达到需求的变更,如下代码所示: 1 public class KuozFF 2 3 { 4 5 public void NormalMethod() 6 7 { 8 9 Console.WriteLine("我是原始方法&qu

Java语法糖(3):泛型

泛型初探 在泛型(Generic type或Generics)出现之前,是这么写代码的: public static void main(String[] args){List list = new ArrayList();list.add("123");list.add("456"); System.out.println((String)list.get(0));}当然这是完全允许的,因为List里面的内容是Object类型的,自然任何对象类型都可以放入.都可以

泛型委托 Predicate/Func/Action

Predicate 泛型委托  表示定义一组条件并确定指定对象是否符合这些条件的方法.此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素.看看下面它的定义: // Summary:    //     Represents the method that defines a set of criteria and determines whether    //     the specified object meets those criteria.    ////

C#的泛型委托Predicate/Func/Action

Predicate<T> 是一个委托,它代表了一个方法,它的定义是: namespace System {    // 摘要:    表示定义一组条件并确定指定对象是否符合这些条件的方法.  // 参数:    //   obj:    要按照由此委托表示的方法中定义的条件进行比较的对象.  // 类型参数:    //   T:    要比较的对象的类型.        // 返回结果:    //     如果 obj 符合由此委托表示的方法中定义的条件,则为 true:否则为 false

Java语法糖1:可变长度参数以及foreach循环原理

语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用了.这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能.或能提升语法的严谨性.或能减少编码出错的机会.Java提供给了用户大量的语法糖,比如泛型.自动装箱.自动拆箱.foreach循环.变长参数.内部类.枚举类.断言(as

C# 委托 (一)—— 委托、 泛型委托与Lambda表达式

C# 委托 (一)—— 委托. 泛型委托与Lambda表达式 2018年08月19日 20:46:47 wnvalentin 阅读数 2992 版权声明:此文乃博主之原创.鄙人才疏,望大侠斧正.此文可转载,然需明根以溯源. https://blog.csdn.net/wnvalentin/article/details/81840339 目录 1 委托的含义 2 委托声明.实例化和调用 2.1 委托的声明 2.2 委托的实例化 2.3 委托实例的调用 3 泛型委托 3.1 Func委托 3.2