委托
C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。
委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。
我们由例子引出委托:
实现返回最大值的功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Text1
{
class Program
{
static int Max(List nums)
{
int max = nums[0];
foreach (var num in nums)
{
if (max < num)
{
max = num;
}
}
return max;
}
static void Main(string[] args)
{
Console.WriteLine(Max(new List() { 1, 2, 3, 4, 5, 6 }));
Console.ReadLine();
}
}
}
利用enum枚举类型和switch语句实现返回最大值或最小值
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Text1
{
enum RetType
{
max,
min,
}
class Program
{
static int Fun(List nums,RetType retType )
{
int max = nums[0];
foreach (var num in nums)
{
switch (retType)
{
case RetType.max:
if (max < num)
{
max = num;
}
break;
case RetType.min:
if (max > num)
{
max = num;
}
break;
}
}
return max;
}
static void Main(string[] args)
{
Console.WriteLine(Fun(new List() { 1, 2, 3, 4, 5, 6 }, RetType.min));
Console.ReadLine();
}
}
}
这个程序完美吗?当热不完美,因为面向对象编程一个重要思想是代码的封闭性,这个代码实现不了封闭。
看一下下面的这个例子,遍历List 挑选出>=10的元素
static List Traverse(List nums)
{
var list = new List();
foreach (var num in nums)
{
if (num > 10)
{
list.Add(num);
}
}
return list;
}
如果让遍历List 挑选出偶数那 只需将num>10改为num%2==0即可,但是第一个例子一样,无法实现封装,
便引出了封装观察以下代码:只要声明一个函数就可以解决这个问题。
static bool Function(int num)
{
return num > 10;
}
static List Traverse(List nums)
{
var list = new List();
foreach (var num in nums)
{
if (Function(num))
{
list.Add(num);
}
}
return list;
}
但是我们不希望是Traverse()调用函数Function()实现的,而是将Function()当成参数传进Traverse();
接下来,引入委托:
第一步:声明委托
第二步:修改形参列表
第三步:传入委托
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Text1
{
class Program
{
delegate bool Function(int num);//声明委托,函数签名
static Function GreaterThan10=delegate(int n){return n>10;};//引入委托 返回大于10的数
static Function Iseven = delegate (int n) { return n % 2 == 0; };//引入委托 返回偶数
static List Traverse(List nums,Function function )//修改形参列表
{
var list = new List();
foreach (var num in nums)
{
if (function(num))
{
list.Add(num);
}
}
return list;
}
static void Main(string[] args)
{
Traverse(new List() { 0, 6, 20, 15, 32 }, GreaterThan10);
Traverse(new List() { 0, 6, 20, 15, 32 }, Iseven);
Console.WriteLine();
Console.ReadLine();
}
}
}
lambda表达式
就是一种对委托的化解写法
语句 lambda: (type var,....)=>{} 多个参数
()=>{} 无参数
var=>{} 一个参数
表达式lambda: 没有{},但是只能有一条语句,和if语句相似
static void Main(string[] args)
{
Traverse(new List() { 0, 6, 20, 15, 32 }, delegate (int n) { return n > 10; });
Traverse(new List() { 0, 6, 20, 15, 32 }, (int n)=> { return n > 10; });
Traverse(new List() { 0, 6, 20, 15, 32 }, (n) => { return n > 10; });
Console.ReadLine();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Text1
{
class Program
{
delegate bool Function(int num);//声明委托,函数签名
static List Traverse(List nums,Function function )//修改形参列表
{
var list = new List();
foreach (var num in nums)
{
if (function(num))
{
list.Add(num);
}
}
return list;
}
static void Main(string[] args)
{
var list=Traverse(new List() { 0, 6, 20, 15, 32 }, (n) => { return n > 10; });
foreach (var num in list)
{
Console.WriteLine(num);
}
Console.ReadLine();
}
}
}
泛型委托
delegate bool Function1(T num);
系统自带的一些泛型委托
Action<> 例 List
.foreach
Func<> 例 List.Sum()
Predicate<> 例 List.Find()
Action<> 相当于无返回值的委托 Action action<>= delegate void Function1
static void Main(string[] args)
{
var list = new List() { 0, 6, 20, 15, 32 };
//foreach (var num in list)
//{
// Console.WriteLine(num);
//}
list.ForEach(i => { Console.WriteLine(i); });
Console.ReadLine();
}
Func<> 相当于返回值的委托
static void Main(string[] args)
{
var list = new List() { 0, 6, 20, 15, 32 };
//list.Sum((n) => {if (n >= 10)return 0; else {return n; }});
Console.WriteLine(list.Sum((n) => { if (n >= 10) return 0; else { return n; } }));
Console.ReadLine();
}
Predicate<> 相当于返回bool的委托
static void Main(string[] args)
{
var list = new List() { 0, 6, 20, 15, 32 };
list.FindAll((n) => n >= 10 );
Console.WriteLine();
Console.ReadLine();
}
案例
泛型委托与lambda表达式结合使用
class Program
{
//delegate bool Function(int n);
//static Function function = delegate (int n) { return n > 5; };
//Func func = delegate (int n) { return n > 10; };
static List Compare(List array, Func func)
{
List res = new List();
foreach (var item in array)
{
if (func(item))
{
res.Add(item);
}
}
return res;
}
static void Main(string[] args)
{
var res= Compare(new List() { 1,2,3,4,5,6,7,8,9}, (n) => { return n > 6; });
foreach (var item in res)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
泛型委托实例
class Program
{
//delegate bool Function(int n);
//static Function function = delegate (int n) { return n > 5; };
static Func function = delegate (int n) { return n > 10; };
static List Compare(List array, Func func)
{
List res = new List();
foreach (var item in array)
{
if (func(item))
{
res.Add(item);
}
}
return res;
}
static void Main(string[] args)
{
var res= Compare(new List() { 1,2,3,4,5,6,7,8,9}, function);
foreach (var item in res)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
表达式树
表达式树核心概念就是:将代码作为数据。它将一些代码表示为一个对象树,树中的每个节点本身都是一个表达式,不同的表达式类型代表能在代码中执行不同操作:二元操作,一元操作,方法调用等等。