要想学好linq to object 我们必须要先学习lambda 表达式,学习lambda 表达式呢我们必须了解匿名函数和匿名类及扩展方法,学习匿名函数,我们必须学会委托,这是本文的宗旨。下面开始第一步。在第一步开始之前,我们做点准备工作,建立一个学生类和一个班级类,类结构如下

   public class Student
    {
        public int Id { get; set; }
        public int ClassId { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public void Study()
        {
            Console.WriteLine("{0} {1}跟着Eleven老师学习.net高级开发", this.Id, this.Name);
        }
    }

    public class Class
    {
        public int Id { get; set; }
        public string ClassName { get; set; }
    }

在准备一个基础数据类

 public class LinqShow
    {
        /// <summary>
        /// 准备数据
        /// </summary>
        /// <returns></returns>
        public List<Student> GetStudentList()
        {
            #region 初始化数据
            List<Student> studentList = new List<Student>()
            {
                new Student()
                {
                    Id=1,
                    Name="打兔子的猎人",
                    ClassId=2,
                    Age=35
                },
                new Student()
                {
                    Id=1,
                    Name="Alpha Go",
                    ClassId=2,
                    Age=23
                },
                 new Student()
                {
                    Id=1,
                    Name="白开水",
                    ClassId=2,
                    Age=27
                },
                 new Student()
                {
                    Id=1,
                    Name="狼牙道",
                    ClassId=2,
                    Age=26
                },
                new Student()
                {
                    Id=1,
                    Name="Nine",
                    ClassId=2,
                    Age=25
                },
                new Student()
                {
                    Id=1,
                    Name="Y",
                    ClassId=2,
                    Age=24
                },
                new Student()
                {
                    Id=1,
                    Name="小昶",
                    ClassId=2,
                    Age=21
                },
                 new Student()
                {
                    Id=1,
                    Name="yoyo",
                    ClassId=2,
                    Age=22
                },
                 new Student()
                {
                    Id=1,
                    Name="冰亮",
                    ClassId=2,
                    Age=34
                },
                 new Student()
                {
                    Id=1,
                    Name="",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {
                    Id=1,
                    Name="毕帆",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {
                    Id=1,
                    Name="一点半",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {
                    Id=1,
                    Name="小石头",
                    ClassId=2,
                    Age=28
                },
                new Student()
                {
                    Id=1,
                    Name="大海",
                    ClassId=2,
                    Age=30
                },
                 new Student()
                {
                    Id=3,
                    Name="yoyo",
                    ClassId=3,
                    Age=30
                },
                  new Student()
                {
                    Id=4,
                    Name="unknown",
                    ClassId=4,
                    Age=30
                }
            };
            #endregion
            return studentList;
        }

    }

 

简单了解委托

 

1. 委托是什么?

其实,我一直思考如何讲解委托,才能把委托说得更透彻。说实话,每个人都委托都有不同的见解,因为看问题的角度不同。个人认为,可以从以下2点来理解:

 (1) 从数据结构来讲,委托是和类一样是一种用户自定义类型

 (2) 从设计模式来讲,委托(类)提供了方法(对象)的抽象。

既然委托是一种类型,那么它存储的是什么数据?

我们知道,委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。调用委托的时候,委托包含的所有方法将被执行。

 

2. 委托类型的定义

委托是类型,就好像类是类型一样。与类一样,委托类型必须在被用来创建变量以及类型对象之前声明。

delegate void MyDel(int x);

 

委托类型声明:

(1) 以deleagate关键字开头。

(2)返回类型+委托类型名+参数列表。

 

3. 声明委托变量

MyDel del1,del2;

 

4. 初始化委托变量

(1) 使用new运算符

new运算符的操作数的组成如下:

  • 委托类型名
  • 一组圆括号,其中包含作为调用列表中的第一个成员的方法的名字。方法可以是实例方法或静态方法。
del1 = new MyDel( 实例方法名 );
del2 = new MyDel( 静态方法名 );

(2)使用快捷语法

快键语法,它仅由方法说明符构成。之所以能这样,是因为在方法名称和其相应的委托类型之间有隐式转换。

del1 = 实例方法名;
del2 = 静态方法名;

 

5. 赋值委托

 由于委托是引用类型,我们可以通过给它赋值来改变包含在委托变量中的方法地址引用。旧的引用会被垃圾回收器回收。

MyDel del;
del = 实例方法名; //委托初始化
del = 静态方法名;//委托重新赋值,旧的引用将被回收

 

6. 委托调用

委托调用跟方法调用类似。委托调用后,调用列表的每个方法将会被执行。

在调用委托前,应判断委托是否为空。调用空委托会抛出异常,这是正常标准调用

if(null != del)
{
     del.Invoke();//委托调用
}

 

 在net 1.1的时代,我们是使用Invoke()方法类调用委托的。但是微软在net 2.0 的时候,我们可以这么去调用委托 直接 del();

if(null != del)
{
     del();//委托调用
}

 

 

7. 综合练习

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    class Program
    {
        public delegate void meathed1();//1 委托的声明   委托是一种类型 
        public delegate int meathed2();//2 可以声明在类的内部,也可以声明在类的外部
        public delegate void meathed3(int id, string name);
        public delegate string meathed4(string msg);
        static void Main(string[] args)
        {
            meathed1 me1 = new meathed1(m1);
            meathed2 me2 = new meathed2(m2);
            meathed3 me3 = new meathed3(m3);
            meathed4 me4 = new meathed4(m4);
            me1.Invoke();
            int result=   me2.Invoke();
            Console.WriteLine(result);
            me3(1, "wbc");
            Console.WriteLine(me4("您吃了吗"));
            Console.Read();

        }
        public static void m1() {
            Console.WriteLine("我是无参数无返回值的方法");
        }
        public static int m2()
        {
            Console.WriteLine("我是无参数有返回值的方法~~~~~~~~~");
            return 123;
        }
        public static void m3(int id, string name)
        {
            Console.WriteLine($"我是有参数无返回值的方法,id={id},name={name}");
        }
        public static string m4(string sparams)
        {
            Console.WriteLine($"我是无参数无返回值的方法 ,参数{sparams}");
            return "参数返回了";
        }
    }
}

 

8. 多播委托

 多播委托(MulticastDelegate)继承自 Delegate ,表示多路广播委托;即,其调用列表中可以拥有多个元素的委托。实际上,我们自定义的委托的基类就是 MulticastDelegate。这句话不好理解,继续往下看

 (第一篇) 一步一步带你了解linq to Object

当我们自己写一个类去继承Delegate 的时候,开发工具提示我 特殊类型不允许被继承,估计这是net 唯一一个特殊类型。

 public abstract class myted : Delegate {

        }

 

我们来看一个案列来使用下多播委托

 meathed1 me1 = new meathed1(m1);
            me1 += m2;
            me1 += m3;
            me1.Invoke();
            me1 -= m2;
            me1();

 

 多播委托:

+= 的时候就是在委托的实例之后加入注册更多的方法,像一个链子,执行的时候按加入的先后顺序执行

-=的时候就是在委托的实例之后移除注册更多的方法。从链子的尾部开始匹配,找到一个完全吻合的移除,没有找到不会触发异常。

注:实例方法因为每一次实例地址的引用不一致,所以无法移除。

 

9. net 框架提供的自带委托

 

8.1.Func委托类型

Func是有返回值的泛型委托,可以没有参数,但最多只有16个参数,并且必须要有返回值。

 

Func<string, int> funcDelegate = new Func<string, int>();

 

 2.Action委托类型
Action是没有返回值的泛型委托,可以没有参数,但最多只有16个参数。 

 Action<string, string> method = new Action<string, string>();

 

  关于泛型这里就不过多介绍了,本人前边写了一篇比较详细。建议大家以后使用委托的时候,尽量使用net 类库自带的委托。

这里扩展下事件的基本使用,事件就是在委托的实例加上一个event 的关键字。所以委托是一种类型,事件就是委托类型的实例。这里只是扩展,不懂不影响学习linq to object 

 

 public void Meta() {

        }
        public delegate void meathed1();
        public class Cat {
            public event meathed1 met_event;
            public meathed1 mea = new meathed1(m1);

            public void Run() {
                mea += m2;
                mea.Invoke();
                met_event = new meathed1(m1);
                met_event += m2;
                met_event.Invoke();

            }
            public static void m1() {

            }
            public static void m2() {

            }
        }
View Code

相关文章: