zoukankan      html  css  js  c++  java
  • 委托、匿名方法、Lambda表达式、泛型委托(自定义、Func、Action、Predicate)、约束泛型类和方法、多窗体传递消息、事件、异步编程、二次控件开发

    1.匿名方法

      没有具体名称,只有委托关键字、方法参数、方法体,所以称之为匿名方法

      匿名方法允许将代码块(方法体部分)通过委托变量作为参数传递,以代替独立定义的方法

      总结:

      方法体要以delegate开头,其后是参数列表,后面紧跟花括号编写方法体,最后以分号结尾

      匿名方法是将方法定义与委托变量两个步骤合在一起,省略了方法的单独定义

      如果一个方法有一个委托类型的参数,可以直接将匿名方法作为实参。

     1         //声明委托
     2         public delegate int MyDelegate(int a, int b);
     3 
     4         static void Main(string[] args)
     5         {//匿名方法
     6             MyDelegate objDel = delegate (int a, int b)
     7             {
     8                 return a + b;
     9             };
    10             Console.WriteLine(objDel(10, 20));
    11             Console.ReadLine();
    12         }
    匿名方法

    2.lambda表达式

      C#3.0引入lambda表达式,lambda表达式是匿名方法更简介使用的一种方式

      (参数列表) => {方法体}  =>读作goes to

      lambda表达式参数列表中的参数类型可以是“明确”类型或者是“推断类型”(可以省略参数类型)

      如果是推断类型,参数数据类型将由编译器根据上下文自动推断出来

      一般情况下还是写参数类型的好,方便自己和他人理解

      如果参数只有一个可以省略();如果方法体只有一行代码可以省略{}

    3.lambda表达式总结

      两种方式:(input args)=>表达式          (input args)=>{语句1;语句2;......}

      举例1:只有一个参数的时候,括号可选   Func<int,bool> del1=(x)=>{return x>0;};

      举例2:可简化为   Func<int,bool> del2=x=>x>0;

      举例3:两个或更多输入参数由逗号分隔    Func<int,int,bool> del3=(x,y)=>x==y;

      举例4:没有参数时,直接输入一个空的括号  Action del4=()=>{...}

     1         //声明委托
     2         public delegate int MyDelegate(int a, int b);
     3         static void Main(string[] args)
     4         {
     5             //一条语句未省略{}
     6             MyDelegate objDel0 = (int a, int b) => { return a + b; };
     7             //一条语句省略{}
     8             MyDelegate objDel1 = (int a, int b) => a + b;
     9             Console.WriteLine(objDel0(10, 20));
    10             Console.WriteLine(objDel1(10, 20));
    11             Console.ReadLine();
    12         }
    Lambda表达式

    4.lambda与匿名方法比较

      Lambda表达式本身就是匿名方法

      Lambda表达式的参数可以允许不指明参数类型,而匿名方法的参数必须明确指明参数类型

      Lambda表达式方法体允许由单一表达式或多条语句组成,而匿名方法不允许单一表达式形式

    5.委托引入

      委托本质:是一个类,继承自System.MulticastDelegate,里面内置了几个方法(Invoke()、BeginInvoke()、EndInvoke())

      委托的声明:public delegate void MyDelete(int num);   细看委托的声明,如果把delegate去掉就是一个方法的声明。

      委托的实例化:实例化委托之前必须写好委托实例传入的方法,这个方法和委托声明必须有相同的返回值和参数。

      委托的调用:Invoke()也可以直接调用。

      委托的三大作用:【1】逻辑解耦,减少重复代码【2】异步多线程【3】多播委托,基于观察者模式

    //【1】委托声明
    public delegate void NoReturnWithPara(int para);
    
    //【2】委托传入的方法
    private void TheMethod(int num)
    {
        Console.WriteLine($"我就是那个数{num}");
    }
    
    public void Show()
    {
        //【3】实例化委托
        NoReturnWithPara noReturnWithPara = new NoReturnWithPara(TheMethod);
        //【4】调用委托实例
        noReturnWithPara.Invoke(22);
        noReturnWithPara(11);
    }
    
    //【5】委托:可以把方法当成参数进行传递
    委托的声明、实例化、调用
    /* 委托解耦的实例说明
     * 背景:一群学生,姓名、年龄、住址各异,要求筛选出特定条件的学生个数。
     * 例如筛选出名字为2个字的学生、年龄大于20的学生、家住昆山的学生、和满足以上所有的学生
     * 最笨的方法(暂不考虑linq),【1】先新建一个list、【2】foreach挨个遍历、【3】判断条件满足、【4】加入list、【5】输出list个数
     * 细分析以上5个步骤:只有步骤3判断条件满足这里不一样,别的四个步骤都一样
     * 四个一样的步骤叫共有逻辑、3判断条件满足叫独有逻辑,解耦解的是这两者之间的耦合关系,在3判断条件满足这里使用委托
     */
    public class DelegateTest
        {
            //准备数据
            public List<Student> students = new List<Student>()
            {
                new Student()
                {
                    Name="张三",
                    Age=36,
                    Address="昆山高新区"
                },
                new Student()
                {
                    Name="李四平",
                    Age=32,
                    Address="昆山开发区"
                },
                new Student()
                {
                    Name="王麻子",
                    Age=18,
                    Address="上海青浦区"
                },
                new Student()
                {
                    Name="赵六",
                    Age=36,
                    Address="天津黑芝麻胡同"
                }
            };
    
            //【1】定义委托
            public delegate bool JudgeDele(Student student);
    
            //【2】准备判断条件
            public bool JudgeNameEqual2(Student student)
            {
                return student.Name.Length == 2;
            }
            public bool JudgeAgeUp20(Student student)
            {
                return student.Age >= 20;
            }
            public bool JudgeAddressInKun(Student student)
            {
                return student.Address.Contains("昆山");
            }
            public bool JudgeAll(Student student)
            {
                return student.Name.Length == 2 && student.Age >= 20 && student.Address.Contains("昆山");
            }
    
            //判断逻辑传递进来+实现共用逻辑,委托解耦,减少重复代码
            public int GetStudents(List<Student> students, JudgeDele dele)
            {
                List<Student> listStu = new List<Student>();
                foreach (Student student in students)
                {
                    if (dele.Invoke(student))//【4】利用委托代替判断方法
                    {
                        listStu.Add(student);
                    }
                }
                return listStu.Count();
            }
        }
    
    
                    //【3】实例化委托
                    DelegateTest delegateTest = new DelegateTest();
                    int NameEqual2 = delegateTest.GetStudents(delegateTest.students, delegateTest.JudgeNameEqual2);
                    int AgeUp20 = delegateTest.GetStudents(delegateTest.students, delegateTest.JudgeAgeUp20);
                    int AddressInKun = delegateTest.GetStudents(delegateTest.students, delegateTest.JudgeAddressInKun);
                    int JudgeAll = delegateTest.GetStudents(delegateTest.students, delegateTest.JudgeAll);
                    Console.WriteLine($"NameEqual2:{NameEqual2}");
                    Console.WriteLine($"AgeUp20:{AgeUp20}");
                    Console.WriteLine($"AddressInKun:{AddressInKun}");
                    Console.WriteLine($"JudgeAll:{JudgeAll}");
    委托解耦实例
    int LingNameEqual2 = (from Student student in delegateTest.students
                          where student.Name.Length == 2
                          select student).Count();
    int LingAgeUp20 = (from Student student in delegateTest.students
                       where student.Age > 20
                       select student).Count();
    int LingAddressInKun = (from Student student in delegateTest.students
                            where student.Address.Contains("昆山")
                            select student).Count();
    int LingJudgeAll = (from Student student in delegateTest.students
                        where student.Name.Length == 2 && student.Age > 20 && student.Address.Contains("昆山")
                        select student).Count();
    Console.WriteLine($"LingNameEqual2:{LingNameEqual2}");
    Console.WriteLine($"LingAgeUp20:{LingAgeUp20}");
    Console.WriteLine($"LingAddressInKun:{LingAddressInKun}");
    Console.WriteLine($"LingJudgeAll:{LingJudgeAll}");
    上方实例其实用linq更简单

    5.多播委托

      多播委托【+=】:为委托实例按顺序增加方法,形成方法链,Invoke时,按顺序依次执行。

      多播委托【-=】:为委托实例按顺序移除方法,从方法链的尾部开始匹配,遇到第一个完全吻合的,移除且只移除一个,没有也不异常。移除时不是同一个实例的方法移除不了。多播委托不能异步(BeginInvoke和EndInvoke)多播委托带返回值Invoke以最后的结果为准。

      多播委托的价值:一个变量保存多个方法,可以增减:invoke的时候可以按顺序执行。

    //【1】定位委托
    public delegate int WithReturnNoPara();
    
    //【2】多播委托的三个方法
    private int GetInt1()
    {
        return 1;
    }
    private int GetInt2()
    {
        return 2;
    }
    private int GetInt3()
    {
        return 3;
    }
    
    public void Show()
    {
        //【3】实例化委托
        WithReturnNoPara withReturnNoPara = new WithReturnNoPara(GetInt1);
        //【4】添加多播委托
        withReturnNoPara += new WithReturnNoPara(GetInt2);
        withReturnNoPara += new WithReturnNoPara(GetInt3);
        foreach (WithReturnNoPara dele in withReturnNoPara.GetInvocationList())
        {//遍历多播委托
            Console.WriteLine($"遍历结果  {dele.Invoke()}");
        }
        Console.WriteLine($"Invoke()方法返回值:{withReturnNoPara.Invoke()}");//多播委托带返回值Invoke以最后的结果为准
        //【5】减去多播委托的一个方法
        withReturnNoPara -= new WithReturnNoPara(GetInt3);
        foreach (WithReturnNoPara dele in withReturnNoPara.GetInvocationList())
        {
            Console.WriteLine($"遍历结果  -=之后{dele.Invoke()}");
        }
        Console.WriteLine($"Invoke()方法返回值:-=之后{withReturnNoPara.Invoke()}");
    }
    多播委托Code

     1 /* 多播委托应用举例,引入事件
     2  * 场景:一直神奇的猫,在它叫了一声之后会其他引发一系列的行为
     3  */
     4 //【1】定义委托
     5 public delegate void MiaoDelegate();
     6 public class Cat
     7 {
     8     //不适用多播委托和事件
     9     //直接调用别的实例别的方法,如果有一系列增删改,会让此方法不稳定
    10     public void Miao()
    11     {
    12         Console.WriteLine("{0} Miao", this.GetType().Name);
    13         new Mouse().Run();
    14         new Baby().Cry();
    15         new Mother().Wispher();
    16         new Brother().Turn();
    17         new Father().Roar();
    18         new Neighbor().Awake();
    19         new Stealer().Hide();
    20         new Dog().Wang();
    21     }
    22 
    23     //分析场景:猫叫了一声,引发一系列后续动作
    24     //可以用多播委托将一系列动作封装出去【甩锅的概念】
    25     //【2】定义委托实例
    26     public MiaoDelegate MiaoDelegateHandler = null;
    27     public void MiaoNew()
    28     {
    29         Console.WriteLine($"{this.GetType().Name}   叫了一声");
    30         if (MiaoDelegateHandler != null)
    31         {
    32             MiaoDelegateHandler.Invoke();
    33         }
    34     }
    35 
    36     //事件的引入
    37     public event MiaoDelegate MiaoDelegateHandlerEvent = null;
    38     public void MiaoNewEvent()
    39     {
    40         Console.WriteLine($"{this.GetType().Name}   叫了一声");
    41         if (MiaoDelegateHandlerEvent != null)
    42         {
    43             MiaoDelegateHandlerEvent.Invoke();
    44         }
    45     }
    46 }
    47 
    48 
    49 //多播委托应用
    50 Cat cat = new Cat();
    51 Console.WriteLine("~~~~~~~~~~~~~多播委托~~~~~~~~~~~~~");
    52 cat.MiaoDelegateHandler += new MiaoDelegate(new Mouse().Run);
    53 cat.MiaoDelegateHandler += new MiaoDelegate(new Baby().Cry);
    54 cat.MiaoDelegateHandler += new MiaoDelegate(new Mother().Wispher);
    55 cat.MiaoDelegateHandler += new MiaoDelegate(new Brother().Turn);
    56 cat.MiaoDelegateHandler += new MiaoDelegate(new Father().Roar);
    57 cat.MiaoDelegateHandler += new MiaoDelegate(new Neighbor().Awake);
    58 cat.MiaoDelegateHandler += new MiaoDelegate(new Stealer().Hide);
    59 cat.MiaoDelegateHandler += new MiaoDelegate(new Dog().Wang);
    60 cat.MiaoNew();
    多播委托之猫叫一声

    5.事件event

       事件是带event关键字的委托的实例,event可以限制变量被外部调用/直接赋值,子类也不能调用。并且事件只能由声明者才能调用。

    /* 多播委托应用举例,引入事件
     * 场景:一直神奇的猫,在它叫了一声之后会其他引发一系列的行为
     */
    //【1】定义委托
    public delegate void MiaoDelegate();
    public class Cat
    {
        //分析场景:猫叫了一声,引发一系列后续动作
        //可以用多播委托将一系列动作封装出去【甩锅的概念】
        //【2】定义委托实例
        public MiaoDelegate MiaoDelegateHandler = null;
        public void MiaoNew()
        {
            Console.WriteLine($"{this.GetType().Name}   叫了一声");
            if (MiaoDelegateHandler != null)
            {
                MiaoDelegateHandler.Invoke();
            }
        }
    
        //事件的引入
        public event MiaoDelegate MiaoDelegateHandlerEvent = null;
        public void MiaoNewEvent()
        {
            Console.WriteLine($"{this.GetType().Name}   叫了一声");
            if (MiaoDelegateHandlerEvent != null)
            {
                MiaoDelegateHandlerEvent.Invoke();
            }
        }
    }
    
    
    Cat cat = new Cat();
    Console.WriteLine("~~~~~~~~~~~~~多播委托~~~~~~~~~~~~~");
    cat.MiaoDelegateHandler += new MiaoDelegate(new Mouse().Run);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Baby().Cry);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Mother().Wispher);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Brother().Turn);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Father().Roar);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Neighbor().Awake);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Stealer().Hide);
    cat.MiaoDelegateHandler += new MiaoDelegate(new Dog().Wang);
    cat.MiaoNew();
    Console.WriteLine("~~~~~~~~~~~~~事件~~~~~~~~~~~~~");
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Mouse().Run);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Baby().Cry);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Mother().Wispher);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Brother().Turn);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Father().Roar);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Neighbor().Awake);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Stealer().Hide);
    cat.MiaoDelegateHandlerEvent += new MiaoDelegate(new Dog().Wang);
    cat.MiaoNewEvent();
    多播委托与事件

      委托与事件的区别和联系?委托是一个类型,事件是委托的一个实例。事件是带event关键字的委托的实例,event可以限制变量被外部调用/直接赋值

    5.事情与程序架构

      事件:可以把一堆可变的动作/行为封装出去,交给第三方来指定。和预定义一样,程序设计的时候,可以把程序分成两部分:一部分是固定的,直接写死;还有不固定的,通过一个事件去开放接口,外部可以随意扩展动作。

      框架:完成固定或通用部分,把可变部分留出扩展点,支持自定义。  

    5.自定义泛型委托

      当一类相同方法类似,但方法的参数类型不一致的时候可以考虑使用泛型委托

      因为是泛型,所以在定义委托时用T表示参数类型,在定义委托变量时再指定方法类型

     1 //1.定义泛型委托 
     2 public delegate T MyDele<T>(T obj1, T obj2);
     3 class Program
     4 {
     5     //2.定义委托方法
     6     static int Add(int a, int b) => a + b;
     7     static double Sub(double a, double b) => a - b;
     8     static void Main(string[] args)
     9     {
    10          //3.定义委托变量
    11          MyDele<int> objIntDele = Add;
    12          MyDele<double> objDouDele = Sub;
    13          //4.使用委托变量
    14          Console.WriteLine(objIntDele(10, 20));
    15          Console.WriteLine(objDouDele(2.2, 5.7));
    16          Console.ReadLine();//使用新特性 using static System.Console;
    17     }
    18 }
    泛型委托
     1     //定义泛型委托
     2     public delegate T MyGenericDeleage<T>(T obj1, T obj2);
     3     class Program
     4     {
     5         static int Add(int a, int b)
     6         {
     7             return a + b;
     8         }
     9         static double Sub(double a, double b)
    10         {
    11             return a - b;
    12         }
    13 
    14         //泛型委托:匿名方法、Lambda表达式
    15         static void Main(string[] args)
    16         {
    17             //【1】使用委托
    18             MyGenericDeleage<int> objDelegate1 = Add;
    19             MyGenericDeleage<double > objDelegate2 = Sub;
    20 
    21             Console.WriteLine(objDelegate1(10,20));
    22             Console.WriteLine(objDelegate2(10, 20));
    23             Console.WriteLine("-----------------");
    24 
    25             //【2】使用匿名方法
    26             MyGenericDeleage<int> objDelegate3 = delegate(int a, int b) { return a + b; };
    27             MyGenericDeleage<double > objDelegate4 = delegate(double  a, double  b) { return a - b; };
    28 
    29             Console.WriteLine(objDelegate3(10, 20));
    30             Console.WriteLine(objDelegate4(10, 20));
    31             Console.WriteLine("-----------------");
    32 
    33             //【3】使用Lambda表达式
    34             MyGenericDeleage<int> objDelegate5 = (a, b) => a + b;
    35             MyGenericDeleage<double> objDelegate6 = (a, b) => a - b;
    36 
    37             Console.WriteLine(objDelegate5(10, 20));
    38             Console.WriteLine(objDelegate6(10, 20));
    39             Console.ReadLine();
    40         }
    41     }
    泛型委托2

     6.Func<T>委托 :最后一个参数为返回值类型

      Func<>委托是微软自定义好的泛型委托

      Func委托声明的最后一个泛型类型是委托所接受方法的返回值类型

     1         static double Add(int a, int b)
     2         {
     3             return a + b;
     4         }
     5         static void Main(string[] args)
     6         {
     7             Func<int, int, double> func0 = Add;
     8             double result = func0(10, 20);
     9             //使用Lambda表达式
    10             Func<int, int, double> func1 = (a, b) => a + b;
    11             Console.WriteLine(func0(10, 20));
    12             Console.WriteLine(func1(10, 20));
    13             Console.ReadLine();
    14         } 
    Func委托的基本使用
    Func<int,int,string> func = (x,y) => (x*y).ToString();
    Consle.WriteLine(func(5,20));
    使用lambda书写Func<>

    7.编写一个方法,从数组中指定位置抽取3个数,求和、求积  int[] nums={10,9,8,7,6,5,4,3,2};

     1         static void Main(string[] args)
     2         {
     3             int[] nums = { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
     4             Console.WriteLine("------不使用委托-------");
     5             Console.WriteLine(GetAdd(nums, 0, 3));
     6             Console.WriteLine(GetMulti(nums, 0, 3));
     7             Console.WriteLine("------使用Func委托-------");
     8             Console.WriteLine(CommmonCalcu(Add, nums, 0, 3));
     9             Console.WriteLine(CommmonCalcu(Multi, nums, 0, 3));
    10             Console.WriteLine("------使用Func委托+Lambda表达式-------");
    11             Console.WriteLine(CommmonCalcu((int a, int b) => a + b, nums, 0, 3));
    12             Console.WriteLine(CommmonCalcu((int a, int b) => a * b, nums, 0, 3));
    13             Console.ReadLine();
    14         }
    15 
    16         static int CommmonCalcu(Func<int,int,int> openation,int[] nums,int from,int to)
    17         {
    18             int result = nums[from]; //无论加乘,都需要使用第一个元素
    19             for (int i = from+1; i <= to; i++)
    20             {
    21                 result = openation(result, nums[i]);
    22             }
    23             return result;
    24         }
    25 
    26         static int Add(int a, int b)
    27         {
    28             return a + b;
    29         }
    30 
    31         static int Multi(int a, int b)
    32         {
    33             return a * b;
    34         }
    35 
    36         static int GetAdd(int[] nums, int from, int to)
    37         {
    38             int result = 0;
    39             for (int i = from; i <= to; i++)
    40             {
    41                 result += nums[i];
    42             }
    43             return result;
    44         }
    45 
    46         static int GetMulti(int[] nums, int from, int to)
    47         {
    48             int result = 1;
    49             for (int i = from; i <= to; i++)
    50             {
    51                 result *= nums[i];
    52             }
    53             return result;
    54         }
    是否使用委托代码比较

      Func委托引用一个有返回值的方法,也就是将方法作为另一个方法的“参数”

    8.Action委托

      Func委托必须要求接受的方法有一个返回值

      Action委托接受一个没有返回值的方法,返回值为void

      应用:在跨线程访问可视化控件的时候经常使用Action委托

    9.Predicate委托

      Predicate<T>委托定义如下:

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

      Predicate<T>委托变量引用一个“判断条件函数”,条件满足返回true。

     1         static void Main(string[] args)
     2         {
     3             List<Student> ListAll = new List<Student>()
     4             {
     5                 new Student(){stuID=10001,stuName="小杨"},
     6                 new Student(){stuID=10002,stuName="小朱"},
     7                 new Student(){stuID=10003,stuName="小王"},
     8                 new Student(){stuID=10004,stuName="小李"},
     9                 new Student(){stuID=10005,stuName="小刘"},
    10                 new Student(){stuID=10006,stuName="小张"},
    11                 new Student(){stuID=10007,stuName="小梅"}
    12             };
    13             //List<T>集合中定义了一个FindAll方法:public T FindAll(Predicate<T> match)
    14             List<Student> list = ListAll.FindAll(s => s.stuID > 10003);
    15             foreach (var item in list)
    16             {
    17                 Console.WriteLine(item.stuName + ":" + item.stuID);
    18             }
    19             Console.ReadLine();
    20         }
    Predicate委托应用

    10.FindAll方法与Linq语句与Linq方法查询比较

     1         static void Main(string[] args)
     2         {
     3             List<Student> ListAll = new List<Student>()
     4             {
     5                 new Student(){stuID=10001,stuName="小杨"},
     6                 new Student(){stuID=10002,stuName="小朱"},
     7                 new Student(){stuID=10003,stuName="小王"},
     8                 new Student(){stuID=10004,stuName="小李"},
     9                 new Student(){stuID=10005,stuName="小刘"},
    10                 new Student(){stuID=10006,stuName="小张"},
    11                 new Student(){stuID=10007,stuName="小梅"}
    12             };
    13             //List<T>集合中定义了一个FindAll方法:public T FindAll(Predicate<T> match)
    14             List<Student> list0 = ListAll.FindAll(s => s.stuID > 10003);
    15             Console.WriteLine("----------使用Predicate委托----------");
    16             foreach (var item in list0)
    17             {
    18                 Console.WriteLine(item.stuName + ":" + item.stuID);
    19             }
    20             Console.WriteLine("----------使用Linq语句查询----------");
    21             var list1 = from stu in ListAll
    22                         where stu.stuID > 10003
    23                         select stu;
    24             foreach (var item in list1)
    25             {
    26                 Console.WriteLine(item.stuName + ":" + item.stuID);
    27             }
    28             Console.WriteLine("----------使用Linq方法查询----------");
    29             var list2 = ListAll.Where(s => s.stuID > 10003)
    30                 .Select(s => s);
    31             foreach (var item in list2)
    32             {
    33                 Console.WriteLine(item.stuName + ":" + item.stuID);
    34             }
    35             Console.ReadLine();
    36         }
    三种方法比较

     11.泛型再结

      委托三大意义:【1】委托解耦【2】异步多线程【3】

      泛型好处:类型安全、方便编码、无需拆装箱操作

      常见泛型:泛型类和泛型方法

      后续深入:泛型委托(自定义泛型委托、Func、Action、Predicate)

      提取不变的,封装变化的

    12.泛型类的规范   public class 类名<T>{类的成员...}

      T:仅仅表示一个占位符,只要符合C#的命名规范即可使用,但一般都是用T

      T:表示一个通用的数据类型,在使用的时候用实际类型代替

      T:泛型类可以在定义中包含多个任意类型的参数,参数之间用多个逗号分隔开

        例如  class MyGenericClass<T1,T2,T3>{...}

        各种类型参数可以用作成员变量的类型、属性或方法等成员的返回类型已经方法的参数类型等。

    13.泛型应用于出入栈

     1     /// <summary>
     2     /// 编写一个入栈和出栈操作的通用类
     3     /// </summary>
     4     /// <typeparam name="T">可以是任意类型</typeparam>
     5     public class MyStack<T>
     6     {
     7         private T[] stack;
     8         private int size;//栈数据容量
     9         private int stackPoint;//当前位置指针
    10 
    11         public MyStack(int size)
    12         {
    13             this.size = size;
    14             stack = new T[size];
    15             stackPoint = -1;
    16         }
    17 
    18         /// <summary>
    19         /// 入栈方法
    20         /// </summary>
    21         /// <param name="item"></param>
    22         public void Push(T item)
    23         {
    24             if (stackPoint >= size)
    25             {
    26                 Console.WriteLine("栈已满");
    27             }
    28             else
    29             {
    30                 stackPoint++;
    31                 stack[stackPoint] = item;
    32             }
    33         }
    34         /// <summary>
    35         /// 出栈方法
    36         /// </summary>
    37         /// <returns></returns>
    38         public T Pop()
    39         {
    40             T data = this.stack[stackPoint];
    41             stackPoint--;
    42             return data;
    43         }
    44     }
    入栈与出栈类
     1         //栈:先进后出
     2         static void Main(string[] args)
     3         {
     4             MyStack<int> objStack = new MyStack<int>(5);
     5             objStack.Push(1);
     6             objStack.Push(2);
     7             objStack.Push(3);
     8             objStack.Push(4);
     9             objStack.Push(5);
    10             Console.WriteLine(objStack.Pop());
    11             Console.WriteLine(objStack.Pop());
    12             Console.WriteLine(objStack.Pop());
    13             Console.WriteLine(objStack.Pop());
    14             Console.WriteLine(objStack.Pop());
    15             Console.ReadLine();
    16         }
    栈应用

     14.default关键字在泛型类中的使用

     1     class MyGenericClass1<T1, T2>
     2     {
     3         private T1 obj1;
     4 
     5         private MyGenericClass1()
     6         {
     7             //obj1 = null; //不能这么用
     8             //obj1 = new T1();//不能随便假设某种类型,这种类型也许没有构造方法,也许是私有的。
     9 
    10             //解决方法:default关键字
    11             obj1 = default(T1);//如果T1是引用类型,就赋值null,如果是值类型就给默认值,对于数值类型就是0,结构类型的话要依据具体的成员类型确定为0或者null
    12         }
    13     }
    default关键字

    15.添加带约束的泛型类

      约束泛型类:泛型类的参数类型受约束,例如泛型类有三个泛型参数,第一个要求必须是值类型、第二个要求必须是引用类型,诸如此类的约束。

     1      class MyGenericCalss2<T1, T2, T3>
     2         where T1 : struct //说明:类型必须是值类型
     3         where T2 : class //说明:类型必须是引用类型
     4         where T3 : new() //说明:类型必须有一个无参数的构造方法,且必须放到最后
     5     //其他类型:基类类型、接口类型
     6     {
     7         public List<T2> ProductList { get; set; }          //产品列表
     8         public T3 Publisher { get; set; }             //发行者
     9         public MyGenericCalss2()
    10         {
    11             ProductList = new List<T2>();
    12             Publisher = new T3();
    13         }
    14         /// <summary>
    15         /// 购买第几个产品
    16         /// </summary>
    17         /// <param name="num">产品索引</param>
    18         /// <returns>购买的产品</returns>
    19         public T2 Buy(T1 num)
    20         {
    21             // return ProductList[num];//直接写是错误的。因为数组通过下标访问的时候必须是int类型,而int和T1又是冲突的
    22             dynamic a = num; //动态类型,在编译时解析
    23             return ProductList[a];
    24         }
    25     }
    dynamic关键字在泛型类中的使用
     1     /// <summary>
     2     /// 课程(产品类)
     3     /// </summary>
     4     class Course
     5     {
     6         /// <summary>
     7         /// 课程名称
     8         /// </summary>
     9         public string CourseName { get; set; }
    10         /// <summary>
    11         /// 学习周期
    12         /// </summary>
    13         public int Period { get; set; }
    14     }
    15     /// <summary>
    16     /// 课程老师(发行人)
    17     /// </summary>
    18     class Teacher
    19     {
    20         public string Name { get; set; }//姓名
    21         public int Count { get; set; }//授课数量
    22     }
    根据泛型类的要求设计参数
     1         static void Main(string[] args)
     2         {
     3             //【1】实例化泛型类型对象
     4             MyGenericCalss2<int, Course, Teacher> myClass2 = new MyGenericCalss2<int, Course, Teacher>();
     5             //【2】给对象属性赋值
     6             myClass2.Publisher = new Teacher() { Name = "常老师", Count = 20 }; //课程的发行人
     7             myClass2.ProductList = new List<Course>()       //课程(产品)列表
     8             {
     9                 new Course(){CourseName =".NET-CS+BS高级工程师VIP班",Period=6},
    10                 new Course(){CourseName =".NET-CS高级工程师VIP班",Period=3},
    11                 new Course(){CourseName =".NET-BS高级工程师VIP班",Period=3},
    12             };
    13             //【3】调用对象方法
    14             Course myCourse = myClass2.Buy(0);
    15             //数据处理
    16             string info = string.Format("我购买的课程是:{0}  学期:{1}个月  课程主讲:{2}",
    17                 myCourse.CourseName,
    18                 myCourse.Period,
    19                 myClass2.Publisher.Name);
    20             Console.WriteLine(info);
    21             Console.ReadLine();
    22         }
    测试带约束的泛型类
     1     /// <summary>
     2     /// 自己写的泛型约束类,模拟一个商品列表,购买以及商品发行人的实例
     3     /// </summary>
     4     class Program
     5     {
     6         static void Main(string[] args)
     7         {
     8             MyGenericClass<int, Course, Teacher> objGeneric = new MyGenericClass<int, Course, Teacher>();
     9             objGeneric.Publisher = new Teacher() { TeaName = "杨老师" };
    10             objGeneric.Products = new List<Course>()
    11             {
    12                 new Course(){CourseName="C#教程",Period=12},
    13                 new Course(){CourseName="VB教程",Period=10},
    14                 new Course(){CourseName="SQLServer教程",Period=6}
    15             };
    16             Course objCourseBuy = objGeneric.Buy(1);
    17             string info = string.Format("购买的课程是{0},课程授课时长是{1},课程主讲老师是{2}", 
    18                 objCourseBuy.CourseName, objCourseBuy.Period, objGeneric.Publisher.TeaName);
    19             Console.WriteLine(info);
    20             Console.ReadLine();
    21         }
    22     }
    23 
    24     /// <summary>
    25     /// 商品交互委托泛型类
    26     /// </summary>
    27     /// <typeparam name="T1">商品索引</typeparam>
    28     /// <typeparam name="T2">商品列表</typeparam>
    29     /// <typeparam name="T3">商品发行人</typeparam>
    30     public class MyGenericClass<T1, T2, T3>
    31         where T1 : struct //T1必须是值类型(值类型包括整型、浮点型、decimal、bool、enum)
    32         where T2 : class  //T2必须是引用类型(引用类型包括数组、class、interface、delegate、object、string)
    33         where T3 : new()  //T3必须有一个空的构造函数
    34     {
    35         public T3 Publisher;  //发行人
    36         public List<T2> Products = new List<T2>();  //商品
    37         public T2 Buy(T1 index)
    38         {
    39             dynamic t1 = index;
    40             return Products[t1];
    41         }
    42     }
    43 
    44     /// <summary>
    45     /// 课程(商品)类
    46     /// </summary>
    47     public class Course
    48     {
    49         /// <summary>
    50         /// 课程名称
    51         /// </summary>
    52         public string CourseName { get; set; } 
    53         /// <summary>
    54         /// 课程周期
    55         /// </summary>
    56         public int Period { get; set; }
    57     }
    58 
    59     /// <summary>
    60     /// 老师(发行人)类
    61     /// </summary>
    62     public class Teacher
    63     {
    64         /// <summary>
    65         /// 老师姓名
    66         /// </summary>
    67         public string TeaName { get; set; }
    68     }
    自己写的约束泛型类

    16.泛型方法

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Console.WriteLine(Add1("大家好", "我是帅气的杨三少"));
     6             Console.WriteLine("10+20={0}", Add1(10, 20));
     7             Console.WriteLine("10.2+20.3={0}", Add1(10.2, 20.3));
     8             Console.WriteLine("10+20.6={0}", Add1(10, 20.6));
     9             Console.ReadLine();
    10         }
    11 
    12         static T Add1<T>(T a, T b)
    13         {
    14             dynamic a1 = a;
    15             dynamic b1 = b;
    16             return a1 + b1;
    17         }
    18 
    19         static T Add2<T>(T a, T b) where T : struct
    20         {
    21             dynamic a1 = a;
    22             dynamic b1 = b;
    23             return a1 + b1;
    24         }
    25     }
    泛型方法(带约束)

     17.使用委托从窗体向子窗体发送消息

        //1.在主窗体定义委托
        public delegate void CountDele(string str);
        public partial class FrmMain : Form
        {
            public FrmMain()
            {
                InitializeComponent();
    
                FrmOther objOther = new FrmOther();
                //4.将委托变量与方法关联
                objOther.objCountDele = ShowCount;
                objOther.Show();
            }
    
            //2.在主窗体定义委托方法
            private void ShowCount(string str)
            {
                lbl_Count.Text = str;
            }
        }
    主窗体内定义委托、定义委托方法、将委托对象与方法关联
     1         //3.定义委托变量
     2         public CountDele objCountDele;
     3         private int count = 0;
     4         public FrmOther()
     5         {
     6             InitializeComponent();
     7         }
     8 
     9         private void btn_1_Click(object sender, EventArgs e)
    10         {
    11             count++;
    12             //5.委托代替方法执行
    13             objCountDele(count.ToString());
    14         }
    从窗体内定义委托变量、委托变量代替方法执行

    18.使用委托主窗体向多个从窗体传递消息

     1     //1.定义委托
     2     public delegate void DeleCount(string str);
     3     public partial class FrmMain : Form
     4     {
     5         //3.定义委托变量
     6         private DeleCount objDeleCount;
     7         private int count = 0;
     8         public FrmMain()
     9         {
    10             InitializeComponent();
    11 
    12             FrmOther01 frm01 = new FrmOther01();
    13             FrmOther02 frm02 = new FrmOther02();
    14             FrmOther03 frm03 = new FrmOther03();
    15             //4.委托变量关联委托方法
    16             objDeleCount += frm01.ShowCount;
    17             objDeleCount += frm02.ShowCount;
    18             objDeleCount += frm03.ShowCount;
    19             frm01.Show();
    20             frm02.Show();
    21             frm03.Show();
    22         }
    23 
    24         private void btn_Add_Click(object sender, EventArgs e)
    25         {
    26             //5.调用委托变量传递消息
    27             count++;
    28             objDeleCount(count.ToString());
    29         }
    30 
    31         private void btn_Clear_Click(object sender, EventArgs e)
    32         {
    33             //5.调用委托变量传递消息
    34             count = 0;
    35             objDeleCount(count.ToString());
    36         }
    37     }
    主窗体定义委托、定义委托变量、关联从窗体的方法、调用委托执行传递
    1         //2.定义委托方法
    2         public void ShowCount(string str)
    3         {
    4             lbl_Count.Text = str;
    5         }
    从窗体定义委托方法

    19.事件event

      事件:事件是对象在外界“刺激”下发生事情,而对外提供的一种消息机制。

      事件就是委托类型。

      事件的两个参与者:

        发送者(Sender):即对象本身,当本身状态发生变化时触发事件,并通知事件的接收者。

        接收者(Receiver):用来处理事件的(事件的关注者),在事件发送者触发一个事件后,会自动执行的内容。

      事件一般的使用规则:委托声明在主窗体类内。委托对象也叫委托实例或委托变量或事件event定义在事件的发送者所在类中,委托调用的方法定义在事件的接收者所在类中,事件关联在主窗体内,事件代替方法实现调用在发送者所在类内。

    20.主窗体统一向多个从窗体发送消息(类似广播),与委托类似

     1     //1.声明委托
     2     public delegate void DeleSendMsg(string msg);
     3     public partial class FrmMain : Form
     4     {
     5         //3.定义事件
     6         public event DeleSendMsg EventSendMsg;
     7         public FrmMain()
     8         {
     9             InitializeComponent();
    10             FrmClient01 frm1 = new FrmClient01();
    11             FrmClient02 frm2 = new FrmClient02();
    12             //4.将主窗体的事件与客户端窗体的接收方法关联起来
    13             EventSendMsg += frm1.Receive;
    14             EventSendMsg += frm2.Receive;
    15             frm1.Show();
    16             frm2.Show();
    17         }
    18 
    19         private void btn_SendMsg_Click(object sender, EventArgs e)
    20         {
    21             //5.使用事件发送消息
    22             EventSendMsg(tb_Msg.Text.Trim());
    23         }
    24     }
    主窗体(消息发送者)
    1         //2.定义客户端窗体的接收方法
    2         public void Receive(string msg)
    3         {
    4             tb_Msg.Text = msg;
    5         }
    客户端(接收消息端)

    21.从窗体向主窗体发送消息,要求在主窗体中显示是来自谁的消息

     1     //1.定义委托
     2     public delegate void DeleSendMsg(string msg);
     3     public partial class FrmMain : Form
     4     {
     5         public FrmMain()
     6         {
     7             InitializeComponent();
     8             FrmClient1 frm1 = new FrmClient1();
     9             FrmClient2 frm2 = new FrmClient2();
    10             //5.事件关联方法
    11             frm1.EventSendMsg += Receice;
    12             frm2.EventSendMsg += Receice;
    13             frm1.Show();
    14             frm2.Show();
    15         }
    16 
    17         //2.定义主窗体接收消息的方法
    18         private void Receice(string msg)
    19         {
    20             tb_Msg.Text += msg + "
    ";
    21         }
    22 
    23         private void btn_ClearMsg_Click(object sender, EventArgs e)
    24         {
    25             tb_Msg.Text = "";
    26         }
    27     }
    主窗体
     1         //3.定义事件
     2         public event DeleSendMsg EventSendMsg;
     3         public FrmClient1()
     4         {
     5             InitializeComponent();
     6         }
     7 
     8         private void btn_SendMsg_Click(object sender, EventArgs e)
     9         {
    10             //4.事件发送消息
    11             EventSendMsg("客户端1的消息:" + tb_Msg.Text.Trim());
    12         }
    从窗体1
     1         //3.定义事件
     2         public event DeleSendMsg EventSendMsg;
     3         public FrmClient2()
     4         {
     5             InitializeComponent();
     6         }
     7 
     8         private void btn_SendMsg_Click(object sender, EventArgs e)
     9         {
    10             //4.事件发送消息
    11             EventSendMsg("客户端2的消息:" + tb_Msg.Text.Trim());
    12         }
    从窗体2

    22.委托与事件的比较

      事件在内部使用可以用“=”,如果是外部使用事件对象必须放在“+=”或“-=”的左边。

      相同点:事件对象本质就是一个私有的委托对象,以及公有的两个方法,add和remove。

      不同点:+=方式,实际上是调用add方法对委托对象进行添加。

          事件对象私有化后,无法直接从外部赋值(内部赋值除外)。例如:事件=null;会出现编译错误,而委托允许这样做。

          好处:避免用户直接将对象清除。比如微软给开发者所定义的各种事件,只允许开发者通过+=方式使用,而不允许开发者把定义好的事件清除掉。Click=null;这是不允许的。只能通过-=方式断开事件,这样能起到保护作用,而委托“太开放”

     23.异步编程  

      异步编程:核心是基于委托实现的。

      委托类型的BeginInvoke(<输入和输出变量>,AsyncCallBack callBack,object ayncState)方法是异步调用的核心
      第一个参数10,表示委托对应的方法实参
      第二个参数CallBack,回调函数,表示异步调用结束后,自动调用的方法
      第三个参数AsyncState,用于向回调函数提供相应的参数信息
      返回值:IAsyncResult异步操作状态接口,封装了异步执行的参数

      委托类型的EndInvoke(IAsyncResult)方法
      参数是BeginInvoke方法的返回值
      返回值:异步执行的结果,返回值类型和委托类型、委托方法的返回值类型一致

     1     //异步编程的核心是基于委托
     2     public partial class FrmMain : Form
     3     {
     4         //异步执行【1】.声明委托
     5         public delegate int DeleExecute(int a);
     6         public FrmMain()
     7         {
     8             InitializeComponent();
     9         }
    10 
    11         //同步执行
    12         private void btnTest1_Click(object sender, EventArgs e)
    13         {
    14             lblInfo1.Text = ExecuteTask1(30).ToString();
    15             lblInfo2.Text = ExecuteTask2(40).ToString();
    16         }
    17 
    18         //异步执行【3】.异步调用
    19         private void btnTest2_Click(object sender, EventArgs e)
    20         {
    21             //定义委托变量,引用相应方法
    22             DeleExecute objDeleExecute = new DeleExecute(ExecuteTask1);
    23 
    24             //通过委托异步调用方法ExecuteTask1
    25             //委托类型的BeginInvoke(<输入和输出变量>,AsyncCallBack callBack,object ayncState)方法是异步调用的核心
    26             //第一个参数10,表示委托对应的方法实参
    27             //第二个参数CallBack,回调函数,表示异步调用结束后,自动调用的方法
    28             //第三个参数AsyncState,用于向回调函数提供相应的参数信息
    29             //返回值:IAsyncResult异步操作状态接口,封装了异步执行的参数
    30 
    31             //【1】.异步调用任务
    32             IAsyncResult result = objDeleExecute.BeginInvoke(50, null, null);
    33             lblInfo1.Text = "异步执行开始计算...";
    34             //【2】.可以并行执行其他任务
    35             lblInfo2.Text = ExecuteTask2(60).ToString();
    36             //【3】.获取异步执行的结果
    37             //委托类型的EndInvoke(IAsyncResult)方法
    38             //参数是BeginInvoke方法的返回值
    39             //返回值:异步执行的结果,返回值类型和委托类型、委托方法的返回值类型一致
    40             int r = objDeleExecute.EndInvoke(result);
    41             lblInfo1.Text = r.ToString();
    42         }
    43 
    44         //异步编程【2】.定义委托方法
    45         private int ExecuteTask1(int a)
    46         {
    47             System.Threading.Thread.Sleep(5000);
    48             return a * a;
    49         }
    50 
    51         private int ExecuteTask2(int a)
    52         {
    53             return a * a;
    54         }
    55     }
    同步编程与异步编程
     1 //同时执行10个任务,第i个任务演示i秒,计算返回i的平方
     2 namespace _016异步编程执行多个任务
     3 {
     4     //【1】.声明委托
     5     public delegate int DeleExecuteTasks(int a,int ms);
     6     public partial class FrmMain : Form
     7     {
     8         //【3】.创建委托变量,因为异步函数和回调函数都要用,所以定义为成员变量
     9         private DeleExecuteTasks objDeleExecuteTasks;
    10         public FrmMain()
    11         {
    12             InitializeComponent();
    13             //【3】.初始化委托变量
    14             objDeleExecuteTasks = new DeleExecuteTasks(ExecuteTask);
    15         }
    16 
    17         //【2】.定义委托方法
    18         private int ExecuteTask(int a, int ms)
    19         {
    20             System.Threading.Thread.Sleep(ms);
    21             return a * a;
    22         }
    23         //【4】.异步同时执行多个任务
    24         private void btn_AsyncTasks_Click(object sender, EventArgs e)
    25         {
    26             //使用循环发布多个任务
    27             for (int i = 1; i < 11; i++)
    28             {
    29                 //开始异步执行
    30                 //前两个参数与异步方法内的参数一致
    31                 //AsyncCallBack:回调函数
    32                 //object @object:最后一个参数是给回调函数的字段AsyncState(IAsyncResult.AsyncState)赋值,如果参数很多可以定义成类或结构
    33                 objDeleExecuteTasks.BeginInvoke(10 * i, 1000 * i, MyAsyncCallBack, i);
    34             }
    35         }
    36 
    37         //【5】.回调函数:作用是当任务完成后的反馈机制,回调函数可以有自己的自定义参数
    38         private void MyAsyncCallBack(IAsyncResult result)
    39         {
    40             int r = objDeleExecuteTasks.EndInvoke(result);
    41             //IAsyncResult.AsyncState用来封装回调函数自定义参数,是object类型
    42             Console.WriteLine("第{0}个任务的执行结果为:{1}", result.AsyncState, r);
    43         }
    44     }
    45 }
    异步编程同时执行多个任务

    24.异步编程总结

      异步编程是建立在委托基础上一种编程的方法

      异步调用的每个方法都是在独立的线程中执行,本质上异步编程就是一种多线程程序,是简化的多线程

      比较适合在后台运行较为耗时的简单任务,并且任务之间要求相互独立,任务中不应该有直接访问可视化控件的代码

      如果后台任务要求必须按照特定顺序执行,或者访问共享资源,则异步编程不太合适,应该选择多线程开发技术

     25.线程Thread

      进程:一个正在运行的程序就是一个进程,操作系统根据进程分配各种资源(比入内存...)

      线程:操作系统为了提高效率会将一个进程分成多个线程,并按照线程来分配CPU执行时间

      线程特点:在具有多个CPU的计算机中,可以并行执行

      Thread类:表示托管线程,每个Thread对象都代表一个托管线程,每个托管线程都会对应一个函数

      ThreadStart 委托定义:public delegate void ThreadStart()    无返回值且无参数

     1         private void btn_TaskThread1_Click(object sender, EventArgs e)
     2         {
     3             //ThreadStart 委托类型 返回值void且无参数
     4             int a = 0;
     5             Thread objThread1=new Thread(delegate()
     6                 {
     7                     for (int i = 1; i <= 10; i++)
     8                     {
     9                         a += i;
    10                         Console.WriteLine("-----1线程------{0}---", a);
    11                         Thread.Sleep(500);
    12                     }
    13                 });
    14             objThread1.IsBackground = true;
    15             objThread1.Start();
    16         }
    17 
    18         private void btn_TaskThread2_Click(object sender, EventArgs e)
    19         {
    20             Thread objThread2 = new Thread(() =>
    21             {
    22                 for (int i = 1; i < 100; i++)
    23                 {
    24                     Console.WriteLine("-----2线程------{0}---", i);
    25                     Thread.Sleep(20);
    26                 }
    27             });
    28             objThread2.IsBackground = true;
    29             objThread2.Start();
    30         }
    多线程

    26.跨线程访问控件

     1         private void btnExecute1_Click(object sender, EventArgs e)
     2         {
     3             Thread objThread1 = new Thread(() =>
     4             {
     5                 for (int i = 1; i < 11; i++)
     6                 {
     7                     if (lblResult1.InvokeRequired)
     8                     {
     9                         lblResult1.Invoke(new Action<string>(s => lblResult1.Text = s), (i * i).ToString());
    10                         Thread.Sleep(100);
    11                     }
    12                 }
    13             });
    14             objThread1.IsBackground = true;
    15             objThread1.Start();
    16         }
    17 
    18         private void btnExecute2_Click(object sender, EventArgs e)
    19         {
    20             Thread objThread2 = new Thread(() =>
    21             {
    22                 for (int i = 11; i < 21; i++)
    23                 {
    24                     if (lblResult2.InvokeRequired)
    25                     {
    26                         lblResult2.Invoke(new Action<string>(s => { lblResult2.Text = s; }), (i * i).ToString());
    27                         Thread.Sleep(200);
    28                     }
    29                 }
    30             });
    31             objThread2.IsBackground = true;
    32             objThread2.Start();
    33         }
    跨线程访问控件

    27.制作二次开发的控件

      1.新建项目——>选择类库——>删除自生成的class1——>添加组件——>进入代码视图——>将ComPonent直接替换成TextBox——>引用添加System.Windows.Forms——>using命名空间——>添加一个ErrorProvider——>编写public的验证是否为空的方法

     1         /// <summary>
     2         /// 判断文本框输入是否为空
     3         /// </summary>
     4         /// <returns>返回值【0为空】【1不为空】</returns>
     5         public int BeginCheckEmpty()
     6         {
     7             if (this.Text.Trim() == "")
     8             {
     9                 errorProvider.SetError(this, "必填项不能为空!");
    10                 return 0;
    11             }
    12             else
    13             {
    14                 errorProvider.SetError(this,string.Empty);
    15                 return 1;
    16             }
    17         }
    判断文本框输入是否为空
     1         /// <summary>
     2         /// 判断文本框输入是否为正整数
     3         /// </summary>
     4         /// <param name="regularExpression">正则表达式</param>
     5         /// <param name="errorMsg">匹配失败后返回的消息</param>
     6         /// <returns>返回值【0匹配失败】【1匹配成功】</returns>
     7         public int BeginCheckRegularExpression(string regularExpression, string errorMsg)
     8         {
     9             if (BeginCheckEmpty() == 0)
    10             {
    11                 return 0;
    12             }
    13             Regex objRegex = new Regex(regularExpression, RegexOptions.IgnoreCase);
    14             if (objRegex.IsMatch(this.Text.Trim()))
    15             {
    16                 errorProvider.SetError(this, string.Empty);
    17                 return 1;
    18             }
    19             else
    20             {
    21                 errorProvider.SetError(this, errorMsg);
    22                 return 0;
    23             }
    24         }
    判断文本框输入是否为正整数
     1         private void btn_Save_Click(object sender, EventArgs e)
     2         {
     3             int a = STB_Name.BeginCheckEmpty();
     4             int b = STB_Age.BeginCheckRegularExpression(@"^[1-9]d*$", "年龄必须为正整数!");
     5             int result = a * b;
     6             if (result!=0)
     7             {
     8                 MessageBox.Show("保存成功");
     9             }
    10         }
    窗体应用
  • 相关阅读:
    关于在组件GIS开发中使用Python的一点补充说明
    shell环境变量以及set,env,export的区别
    快速配置 Samba 将 Linux 目录映射为 Windows 驱动器
    Expect 教程中文版
    rpm 包管理
    .bash_profile和.bashrc的什么区别
    grep 零宽断言
    自动化测试
    dialog shell下的gui设计 代替繁杂libncurses编程
    x11 gtk qt gnome kde 之间的区别和联系
  • 原文地址:https://www.cnblogs.com/yangmengke2018/p/10939667.html
Copyright © 2011-2022 走看看