委托定义了一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。 其参数列表和返回类型匹配的方法(静态或实例)分配给该类型的变量,然后(使用适当参数)直接调用该方法,或将其作为参数本身传递给另一方法再进行调用
为简化开发过程,.NET 包含一组委托类型,程序员可重用这些类型而无需创建新类型。
这些类型是 Func<>
、Action<>
和 Predicate<>
,可以使用它们而无需定义新的委托类型。
但是,即使使用此方法,仍有许多可以丢弃的代码。 此时就需要使用 lambda 表达式
Lambda 表达式是指定委托的另一种方式
原始委托的申明及使用:
using System;
namespace ConsoleApp3
{
internal class Program
{
//委托的本质是一个密封类,它的父类是:MulticastDelegate
//委托说白了就是一个数据类型,就像string 类型接收字符串数据 int类型接收整形数据, 而委托类型接收方法
//定义一个返回值为Int 带两个参数的委托
public delegate int SumDelegate(int x, int y);
static void Main(string[] args)
{
Type type = typeof(SumDelegate);
Console.WriteLine(type.IsClass);
Console.WriteLine(type.BaseType.Name); //查看委托的父类名称:MulticastDelegate ;MulticastDelegate是一个抽象类
Console.WriteLine(type.BaseType.BaseType.Name); //查看委托的父类的父类名称:Delegate ; Delegate是一个abstract抽象类
//委托的使用
//第一种用法:指定方法
SumDelegate sumdel = new SumDelegate(SumFun);
var sumA = sumdel.Invoke(1, 2); //通过Invoke来调用:sum的值是3
var sumB = sumdel(1, 2); //也可以直接调用:sum的值是3
//第二种用法:匿名委托
SumDelegate sumdel1 = delegate (int a, int b) { return a + b; };
var sum1A = sumdel1.Invoke(2, 3); //通过Invoke来调用:sum1A的值是5
var sum1B = sumdel1(2, 3); //也可以直接调用:sum1B的值是5
//第三种用法:直接赋值一个方法:这是第一种的简化版
SumDelegate sumdel2 = SumFun;
var sum2A = sumdel2.Invoke(3, 4); //通过Invoke来调用:sum2A的值是7
var sum2B = sumdel2(3, 4); //也可以直接调用:sum2B的值是3
//第四种用法:朗姆达表达式:这是第二种的简化版
SumDelegate sumdel3 = (a, b) => a + b;
var sum3A = sumdel3.Invoke(3, 4);
var sum3B = sumdel3(3, 4);
//使用委托的案列:求数组的最大值
string[] strArr = { "abc", "EDdee", "edd", "DEFrr" };
int[] intArr = { 2, 8, 9, 63, 12, 3 };
var strArrMaxValue = GetArrMaxValue(strArr, (x, y) =>
{
var dvalue = string.Compare(x, y, false); //第三个参数ignoreCase:表示是否区分大小写; true表示不区分大小写,false表示区分大小写。
return dvalue < 0;
});
var intArrMaxValue = GetArrMaxValue(intArr, (x, y) => { return x - y < 0; });
}
private static int SumFun(int a, int b)
{
return a + b;
}
private static T GetArrMaxValue<T>(T[] arr, Func<T, T, bool> func)
{
T max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
var booVal = func(max, arr[i]);
if (booVal)
{
max = arr[i];
}
}
return max;
}
}
}
匿名委托,也称作匿名方法
namespace ConsoleTest
{
public delegate void Mydeleage(int x, int y);//定义了一个委托
class Program
{
static void Main(string[] args)
{
//这里定义了一个匿名委托:delegate(int x, int y){ Console.WriteLine(x + y); };
//定义的这个匿名委托需要有一个相对应的委托变量去指向它。【匿名委托也叫匿名方法】
Mydeleage del = delegate(int x, int y)
{
Console.WriteLine(x + y);
};
}
}
}
Action 与 Func委托
Action和 Func是.NET中已经声明好的两种委托 ,一种没有返回值,一种可以有返回值
Action:表示无返回值的委托
Func :表示带返回值的委托
申明Action 与 Func委托案例:
//-------------------------------无返回值的委托Action-----------------------------------
//无返回值,无参数的委托,相当于public delegate void action(),
Action action
//无返回值,带一个string类型参数的委托,相当于public delegate void action(string str);
Action<string> action
//-----------------------------有返回值的委托Func----------------------------------------
//返回值为int,带一个string类型参数的委托:注意最后一个参数为返回值;
//它相当于public delegate int func(string str);
Func<string,int> func
//返回值为int,无参数的委托:它相当于public delegate int func();
Func<int> func;
利用委托对List进行扩展一个Where方法 案例:
using System;
using System.Collections.Generic;
namespace ConsoleApp3
{
public static class ExtenssionLinq
{
//自己封装一个Where数据刷选方法:它是一个对List的扩展
public static List<T> MyWhere<T>(this List<T> list, Func<T, bool> func)
{
List<T> source = new List<T>();
foreach (var item in list)
{
if (func(item))
{
source.Add(item);
}
}
return source;
}
}
}
Lambda表达式指定委托案列:
Lambda表达式是一种简洁而强大的编程语法,它可以用于创建匿名函数或委托。
通过Lambda表达式,我们可以轻松地编写内联的、即时执行的函数,无需额外定义命名函数或委托。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 拉姆达表达式
{
class Program
{ //Action action是一个没有返回值,没有参数的委托,它相当于 public deletage void action()
public void SayHello(Action action)
{
action(); //执行这个委托
}
static void Main(string[] args)
{
Program p = new Program();
p.SayHello( //这里是调用SayHello方法
//实现委托,指定委托注册处理函数为Console.WriteLine()方法
() => { Console.WriteLine(" 哈哈"); } //既然这个委托没有参数,就可以写成()=> { 表达式 }。
);
Console.ReadKey();
}
}
}
委托与Lambda表达式的关系:
lambda 表达式只是指定委托的另一种方式
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 朗姆达表达式
{
//“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型
class Program
{
public delegate int del(int x);
static void Main(string[] args)
{
del mydel = (x) => //如果拉姆的这有一个参数的时候可以简写,即:del mydel=x=>x*x;
{
return x * x;
};
int i = mydel(5);
Console.WriteLine(i); //输出25
//------------------------------------------只有一个int参数,返回值为int类型的委托
Func<int, int> fun = x => x * x;
int j = fun(6);
Console.WriteLine(j); //输出36
Func<int, int> fun2 = (x) => //这一句与上面的fun委托效果是一样的。只是这里是全写,上面是简写
{
return x * x;
};
int j2 = fun2(6);
Console.WriteLine(j2); //输出36
//------------------------------------------只有2个int参数,返回值为int类型的委托
Func<int, int, int> fun3 = (x, y) => { return x * y; };
int j3=fun3(5, 6);
Console.WriteLine(j3); //输出30
//这是一个有2个int参数,返回值为int的委托,相当于 public delegate int fun4(int a, int b);
Func<int, int, int> fun4 = (int a,int b) =>
{
if (a > b)
{
return a;
}
else
{
return b;
}
};
int j4 = fun4(8, 18);
Console.WriteLine(j4); //输出18
//与上文使用delegate定义匿名方法的作用相同,Lambda表达式的作用也是为了定义一个匿名方法。因此,下面使用delegate的代码和上面是等价的:
Func<int, int, int> fun5 = delegate(int a, int b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
};
int j5 = fun4(8, 18);
Console.WriteLine(j5); //输出18
//那么您可能就会问,这样看来Lambda表达式又有什么意义呢?Lambda表达式的意义便是它可以写的非常简单,例如之前的Lambda表达式可以简写成这样:
Func<int, int, int> max = (a, b) =>
{
if (a > b)
{
return a;
}
else
{
return b;
}
};
int j6 = max(8, 18);
Console.WriteLine(j6); //输出18
//-----------------------------------------只有一个参数,没有返回值的委托的朗姆达表达式
Action<int> action = (x) =>
{
Console.WriteLine(x * x);
};
action(8); //调用action委托。输出64
Action<string> action3 = n => { string s = n + "你好"; Console.WriteLine(s); };
action3("Hi"); //调用action3委托。输出 Hi你好
//-----------------------------------------没有参数,没有返回值的委托的朗姆达表达式
Action action2 = () => { Console.WriteLine("中国"); };
action2(); //调用action2委托。输出 中国
//他相当于:先定义一个委托,然后让委托指向Console类下面的WriteLine方法
// public delegate void action2()
// action2 action22 = new Program.action2(Console.WriteLine);
//-----------------------------------------------------------------------
int[] oddNumbers = { 8, 3, 5, 9, 15, 1, 6 };
//Count是返回一个数字,表示在指定的序列中满足条件的元素数量。
int result = oddNumbers.Count((s) => { return s % 2 == 1; }); //求 oddNumbers数组中各个元素除2取余等于1的数字个数
//oddNumbers.Where((r) =>
// {
// return r % 2 == 1;
// }).Count();
Console.WriteLine(result); //输出5
//FindAll是检索指定谓词定义的条件匹配的所有元素
List<int> slist = new List<int> { 1, 4, 2, 7, 3 };
var ss = slist.FindAll(d => d % 2 == 0); //检索出slist数据集中除2等于0的所有元素
foreach (var item in ss)
{
Console.WriteLine(item); //输出4,2
}
Console.ReadKey();
}
}
}
朗姆达表达式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 朗姆达表达式2
{
class Program
{
static void Main(string[] args)
{
List<string> strList = new List<string>() { "1", "8", "5", "16", "2", "25" };
List<int> intList = new List<int>() { };
List<int> eveList = new List<int>() { };
List<int> squareList = new List<int>() { };
foreach (var item in strList)// 将strList的元素都转成int类型的整数,然后给他添加到intList中
{
intList.Add(int.Parse(item));
}
foreach (var item in intList)// 找出元素中所有偶数,然后给它添加到eveList集合中
{
if (item % 2 == 0)
{
eveList.Add(item);
}
}
foreach (var item in eveList) // 算出每个数的平方,然后给它添加到squareList集合中
{
squareList.Add(item * item);
}
squareList.Sort();// 按照元素自身排序
foreach (var item in squareList)
{
Console.Write(item + " ");
}
//--------------------------------------------用朗姆达表达式实现
var list= strList
.Select(s => int.Parse(s)) // 将strList的元素都转成int类型的整数
.Where(y => y % 2 == 0) // 找出元素中所有偶数
.OrderBy(z => z) // 按照元素自身排序
.Select(a => a * a) // 算出每个数的平方
.ToList(); //构造一个List
foreach (var item in list)
{
Console.Write(item + " ");
}
Console.Read();
}
}
}
扩展:对IEnumerable类进行扩展
namespace Demo
{
static class JiHeExt
{
public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> data, Func<T, bool> fun)
{
List<T> list = new List<T>();
foreach (T item in data) //其实这个data就是int[] arr = { 1, 5, 3, 9, 20, 6, 78, 15 };这个数组
{
if (fun(item) == true)//判断遍历的这条数据是否满足条件fun
{
list.Add(item);
}
}
return list;
}
}
class Program
{
static void Main(string[] args)
{
int[] arr = { 1, 5, 3, 9, 20, 6, 78, 15 }; //int[]是实现了IEnumerable接口的
var myarr = arr.MyWhere(i => i > 10); //的到:20,78,15
}
}
}