C#笔记11

本文详细介绍了C#中的Action和Func委托,包括它们的用法、多播委托的概念以及如何处理没有返回值和有返回值的方法。此外,还讲解了匿名方法和Lambda表达式的使用,以及事件的声明和触发。最后,通过实例展示了如何使用委托进行冒泡排序,并利用泛型和委托实现对非int类型的数据排序。文章深入浅出地阐述了C#中委托和事件的核心概念及其在实际编程中的应用。
摘要由CSDN通过智能技术生成

Action委托

系统预定义的一个委托类型

action委托只能指向一个没有返回值的方法

如果指向方法时存在多个相同名称的方法,系统会自动匹配适合的方法

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

namespace learn
{
    class Program
    {
        static void Ret()
        {
            Console.WriteLine("调用没有返回值的方法");
        }
        static void OutPut(int a)
        {
            Console.WriteLine("输出" + a);
        }
        static void OutPut(string a)
        {
            Console.WriteLine("输出" + a);

        }

        static void Main(string[] args)
        {
            void OutPut(int a)
            {
                Console.WriteLine(a + "得到");
            }
            //但如果在主函数内定义一个相同名称的方法,会出现冲突,委托会自行寻找最近的方法
            //action委托只能指向一个没有返回值的方法
            Action a = Ret;
            a();
            Action<int> b = OutPut;
            //Action<string> b1 = OutPut;
            b(100);
            //b1("aa");
            //action的拓展用法,
            //这里定义一个委托指向没有返回值,有int参数传递过去的方法。
        }
    }
}

多个参数 Action<int,string> a;即可

Func委托

要求其指向的方法必须得有一个返回值

Func传递参数需要使用泛型,一般Func的泛型除了最后一个是返回值的类型,前面全是传递参数的类型

Func<int,string> a 这里指传递int类型参数,返回string类型数据

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

namespace learn
{
    class Program
    {
        static int Ret(string a)
        {
            int b = Convert.ToInt32(a);
            return b;
        }
        static void Main(string[] args)
        {
            Func<string, int> a;
            //最后一个泛型是返回值类型
            //前面其他则是传递参数类型
            a = Ret;//指向ret方法
            Console.WriteLine(a("1241"));
        }
    }
}

冒泡排序法

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

namespace learn
{
    class 冒泡排序
    {
        static void Main(string[] args)
        {
            int[] array = new int[5] { 1, 4, 2, 9, 6 };
            Sort(array);
        }
        static void Sort(int[] Array)
        {
            bool a = true;
            while (a)
            {
                for (int i = 1; i < Array.Length; i++)
                {
                    if (Array[i] < Array[i - 1])
                    {
                        int n = Array[i];
                        Array[i] = Array[i - 1];
                        Array[i - 1] = n;
                        continue;//结束当前一层所有循环,进行下一次判断
                    }
                    a = false;
                }
            }

            Console.WriteLine("排序完成");
            for (int i = 0; i < Array.Length; i++)
            {
                Console.Write(Array[i] + "  ");
            }
        }
    }
}

冒泡排序扩展

对非int类型进行排序

使用泛型加委托的方式

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

namespace learn
{
    class 冒泡排序扩展
    {
        static void Main(string[] args)
        {
            Employee[] employee = new Employee[3];
            //for (int i = 0; i < 3; i++)
            //{
            //    Console.Write("输入姓名:");
            //    string name = Console.ReadLine();
            //    Console.Write("输入工资:");
            //    int salary = Convert.ToInt32(Console.ReadLine());
            //    employee[i] = new Employee(name, salary);
            //}
            employee[0] = new Employee("li", 13);
            employee[1] = new Employee("ai", 31);
            employee[2] = new Employee("ao", 22);

            CommonSort<Employee>(employee, Employee.Compare);
            //C#中传递数组是传递数组的地址,所以无需返回值
            //因为是对象数组,类型是声明对象的类Func<>委托传递的是方法
            foreach (Employee em in employee)
            {
                //Console.WriteLine(em.Name + ":" + em.Salary);
                //这里的em默认是em.ToString()
                //这里输出的是em对象的字符串
                //所以我们得重写ToString()方法,或者直接使用em.Salary访问数值
                Console.WriteLine(em);//em的Tostring方法被重写了
            }
        }

        //一个静态的,通用冒泡排序方法
        static void CommonSort<T>(T[] Array, Func<T, T, bool> Compare)
        {
            bool a = true;
            while (a)
            {
                for (int i = 1; i < Array.Length; i++)
                {
                    //因为泛型T不能使用双目运算符判断,所有我们将比较的方法抛给调用本方法的程序
                    if (Compare(Array[i], Array[i - 1]))
                    {
                        T n = Array[i];
                        Array[i] = Array[i - 1];
                        Array[i - 1] = n;
                        continue;//结束当前一层所有循环,进行下一次判断
                    }
                    a = false;
                }
            }

            //Console.WriteLine("排序完成");
            //for (int i = 0; i < Array.Length; i++)
            //{
            //    Console.Write(Array[i] + "  ");
            //}
        }

    }


    class Employee
    {
        private string name;//名称
        private int salary;//工资

        public Employee(string name, int salary)
        {
            this.name = name;
            this.salary = salary;
        }//构造函数,赋予初始数据

        public string Name { get => name; private set => name = value; }
        public int Salary { get => salary; private set => salary = value; }
        //使用private set保护数据不会被直接更改。

        public static bool Compare(Employee e1, Employee e2)
        {
            //比较e1和e2
            if (e1.Salary < e2.Salary)
                return true;
            else
                return false;
        }

        public override string ToString()
        {
            return Name + ":" + Salary;
        }//重写Employee的ToString方法

    }
}

多播委托 

使用+= -=来增减委托指向的方法,广播,多播委托形象化就是将一种数据广播出去。

如果没有指向的方法,会报错。

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

namespace learn
{
    class 多播委托
    {
        static void test1(int n)
        {
            Console.WriteLine(n);
        }
        static void test2(int n)
        {
            Console.WriteLine(n);
        }
        static void Main(string[] args)
        {
            Action<int> a = test1;
            //a = test2;//这里只是将上面的引用覆盖掉
            a += test2;//在指向test1的同时指向test2
                       //a -= test1;//使用-= 方法名可以去掉不需要的委托
            a(1);//同时使用两个指向的方法
                 //同样的,可以将数值广播给两个方法
            a -= test1;
            a -= test2;
            //a(1);//这里就会报错
            if (a != null)//所以习惯上要先判断委托是否为空在调用
                a(1);
        }
    }
}

所以习惯上要先判断委托是否为空在调用

多播委托包含一个逐个调用的委托集合,如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。

取得多播委托中所有方法的委托

声明一个委托对象Delegate delegate = 委托名.GetInvocationList();

通过委托的GetInvocationList方法获取多播委托的方法
然后使用DynamicInvoke方法实现委托的方法

Delegate[] delegates = a.GetInvocationList();//声明一个委托对象
            foreach (Delegate d in delegates)//遍历委托
            {
                d.DynamicInvoke(3);

                //如果委托内的方法不需要参数,直接调用即可,如果需要参数,需要写上参数
            }

匿名方法

没有名字的方法

本质上是一个方法,只是没有名字

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

namespace learn
{
    class 匿名方法
    {
        static int Add(int a, int b)
        {
            return a + b;
        }
        static void Main(string[] args)
        {
            //Func<int, int, int> Ret = Add;
            Func<int, int, int> ret = delegate (int a, int b)
              {
                  return a + b;
              };
            //这里的delegate就是匿名方法
            ret += delegate (int a, int b)
            {
                return a - b;
            };//可以通过多播委托增减匿名方法,减少代码量
            Delegate[] delegates = ret.GetInvocationList();
            foreach (Delegate de in delegates)
            {
                Console.WriteLine(de.DynamicInvoke(2, 3));
            }//可以通过GetInvocationList DynamicInvoke方法获取多播委托引用的方法的返回值
            Console.WriteLine(ret(2, 3));
            //直接使用则会返回最后一个方法的返回值
        }
    }
}

Lambda表达式

匿名方法的一个简写形式

Func<int, int, int> ret = (a, b) =>
{
      return a + b;
};

不需要指定参数类型,因为在Func中已经指定了传递的参数类型

=>左边列出参数,如果只有一个参数可以直接写a=>

Lambda表达式也可以在方法中使用
public static int ret1() => 1;//如果只有一行语句,都可使用Lambda表达式

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

namespace learn
{
    class Lambda表达式
    {
        static void Main(string[] args)
        {
            //Func<int, int, int> ret = delegate (int a, int b)
            //{
            //    return a + b;
            //};
            Func<int, int, int> ret = (a, b) =>//这里就是Lambda表达式写法,其是为了简化匿名方法的写法
            {
                return a + b;
            };
            Console.WriteLine(ret(90, 60));
            Console.WriteLine(ret1());
        }
        public static int ret1() => 1;//如果只有一行语句,都可使用Lambda表达式
    }
}

事件

在声明委托的基础上,加上event

和一般委托的区别,在声明上,事件只能在类里声明不能在方法里声明

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

namespace learn
{
    class Program
    {
        public delegate void Mydelegate();
        //public Mydelegate mydelegate;//声明了一个委托类型的变量和作为类的成员
        public event Mydelegate mydelegate;
        //加上event就是一个事件
        //事件只能在类里声明,不能在方法里声明
        static void Main(string[] args)
        {

            Program p = new Program();
            p.mydelegate = () =>
            {
                Console.WriteLine(1);
            };
            p.mydelegate();
        }
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值