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();
}
}
}