c#基础知识---委托,匿名函数,lambda
作者:王延领 发布时间:2023-06-12 18:18:07
目录
前言:
1.委托的声明
1.1.delegate
1.1.1. 0-23个参数,可以有返回值也可以没有返回值
1.1.2.委托的调用
1.1.3.委托的多播
1.2.Action
1.3.Func
1.4.predicate
2.委托的实例化
2.1.delegate
2.2.Action的使用
2.3.Func的使用
2.4 委托实现冒泡排序
3.匿名函数与lambda
3.1什么是匿名函数
3.2.lambda
4.综上:
前言:
C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于实现事件和回调方法。所有的委托都派生自 System.Delegate 类。把一个方法当作参数传递,让其它方法进行调用执行。
1.委托的声明
委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。
1.1.delegate
1.1.1. 0-23个参数,可以有返回值也可以没有返回值
public delegate int MyDelegateEventHandler (string parm);
注:(1).此委托指向的方法必须是参数为string类型,返回类型为int类型的。其他声明类比所得。
(2).EventHandler是c# 命名规范,当然我理解规范就是可以随意啦。
(3).委托调用时必须判断是否为null不然会报异常
(4).事件也是一种委托
1.1.2.委托的调用
MyDelegateEventHandler fun=new MyDelegateEventHandler(method);
or
MyDelegateEventHandler fun=method;
// fun不为空,则调用回调方法
if (fun!= null)
{
fun(val);
}
//fun?.Invoke(val); 简化版本调用
1.1.3.委托的多播
每个委托都只包含一个方法调用,如果调用多个方法,就需要多次显示调用这个委托。如果同一个委托调用多个方法,我们就可以用多播委托
public delegate void MyDelegate ();
public voidMyMethod()
{
//#
}
public void MyMethod1()
{
//#
}
public void MyMethod2()
{
//#
}
MyDelegateEnventHander myDelegate;
myDelegate=new MyDelegateEventHander(MyMethod);
myDelegate+=new MyDelegateEventHander(MyMethod1);
...........
//调用
myDelegate();
注:
1.委托对象可使用 "+" 运算符进行合并;
2."-" 运算符可用于从合并的委托中移除组件委托;
3.委托指定方法类型必须一致;
4.返回类型一般为void,但非必须;
5.GetInvocationList获取委托索引
if (MyDelegate != null)
System.Delegate[] dels = MyDelegate .GetInvocationList();
for (int i = 0; i < dels.Length; i++)
{
MyDelegate -= dels[i] as MethodDelegate;
}
以上是利用GetInvocationList获取委托索引的一个简单应用。
1.2.Action
Action至少0个参数,至多16个参数,无返回值。
Action 表示无参,无返回值的委托
Action<int,string> 表示有传入参数int,string无返回值的委托
Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托
Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托
public void Test<T>(Action<T> action,T p)
{
action(p);
}
1.3.Func
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void
Func是无返回值的泛型委托
Func<int> 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托
1.4.predicate
1.predicate 是返回bool型的泛型委托;
2.predicate<int> 表示传入参数为int 返回bool的委托;
3.Predicate有且只有一个参数,返回值固定为bool;
public delegate bool Predicate<T> (T obj)
2.委托的实例化
2.1.delegate
public delegate int MyDelegateEventHandler (string parm)
public int MyMethod(string parm)
{
//#
}
MyDelegateEventHandler MyDelegate=new MyDelegateEventHandler(MyMethod)
注:委托实例化的时候,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。委托参数中的方法不含参数。
2.2.Action的使用
public void Test<T>(Action<T> action, T p)
{
action(p);
}
private void Action(string s)
{
#
}
//调用
Test<string>(Action,"wyl");
2.3.Func的使用
public int Test<T1, T2>(Func<T1, T2, int> func, T1 a, T2 b)
{
return func(a, b);
}
private int Fun(int a, int b)
{
#
}
//调用
Test<int,int>(Fun,100,200)
2.4 委托实现冒泡排序
//定义对象
class Student
{
public string Name { get; private set; }
public decimal Scores{ get; private set; }
public Student(string name, decimal scores)
{
this.Name = name; this.Scores= scores;
}
public override string ToString()
{
return string.Format("{0},{1:C}",Name,Scores);
}
public static bool CompareScores(Student e1,Student e2)
{
return e1.Scores< e2.Scores;
}
}
//利用委托实现冒泡
class BubbleScores
{
public static void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Count - 1; i++)
{
if (comparison(sortArray[i + 1], sortArray[i]))
{
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
}
//调用
Student[] students={new Student("wyl", 100),#};
BubbleSorter.Sort(students, Student.CompareScores);
foreach(var student in students)
Console.WriteLine(student);
3.匿名函数与lambda
3.1什么是匿名函数
匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用。
可以使用匿名函数来初始化命名委托(无需取名字的委托),或传递命名委托(而不是命名委托类型,传递一个方法块,而不是委托类型)[callback的方式]作为方法参数。
MyDelegate funDelegate = delegate(string s) { Console.WriteLine(s); };
funDelegate ("this is anonymous delegate");
3.2.lambda
lambda表达式实际上是一个匿名函数。编译器在看到lambda之后会在类中自动定义一个新的私有方法。lambda必须匹配委托!其中lambda是从c#3.0后引用的
lambda的语法:
参数 => 方法体。
=>左边是要传入的参数,本例中是传入一个Int类型的变量,=>右边是具体的代码。
//如果不传递参数:
()=>Console.WriteLine("Hello World!")
//传递一个参数:
(int n)=>Console.WriteLine(n.ToString())
//或者去掉()和int 编译器会自己推断类型:
n=>Console.WriteLine(n.ToString())
//传递多个参数:
(int n ,int m)=>Console.WriteLine(n+m)
//或者编译器自己推断类型:
(n , m)=>Console.WriteLine(m+n)
4.综上:
1.委托类似于 C++ 函数指针。
2.委托允许将方法作为参数进行传递。
3.委托可用于定义回调方法。
4.委托可以链接在一起;多播。
5.方法不必与委托签名完全匹配。
来源:https://www.cnblogs.com/wyl1924/p/13138793.html


猜你喜欢
- 本文实例讲述了java版微信公众平台消息接口应用方法。分享给大家供大家参考,具体如下:微信公众平台现在推出自动回复消息接口,但是由于是接口内
- 一个简单好理解的例子,复制过去就能用,能看到效果首先对功能的思考,他怎么去实现1.制定udp广播的端口(如果收发用同一个端口就会一直接收到自
- 本文为大家分享了Java多线程实现Runnable方式的具体方法,供大家参考,具体内容如下(一)步骤 1.定义实现Runnable
- 最近项目进行适配的时候发现部分(如华为手机)存在底部虚拟按键的手机会因为虚拟按键的存在导致挡住部分界面,因为需要全屏显示,故调用虚拟按键隐藏
- 实现字符串库函数功能有些时候我们可能会被限制无法使用库函数,这个时候我们需要编写自己的库函数。但了解了字符串库函数的功能之后,想要实现并不困
- 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工
- 双保险线程,每次启动2个相同的线程,互相检测,避免线程死锁造成影响。两个线程都运行,但只有一个线程执行业务,但都会检测对方的时间戳 如果时间
- 本文内容大多基于官方文档和网上前辈经验总结,经过个人实践加以整理积累,仅供参考。1、日期时间字符串转换成毫秒@Testpublic void
- 本文实例为大家分享了Android实现3D云标签效果的具体代码,供大家参考,具体内容如下一、自定义Viewpublic class TagC
- asp.net core 中已经自带了一个官方的依赖注入框架,现在想把它应用到控制台程序中,控制台程序是最简洁的代码结构,摒除了其他一堆嵌入
- using System.Collections.Generic;using System.Text;using System;namesp
- 本文实例讲述了Android编程开发之NotiFication用法。分享给大家供大家参考,具体如下:notification就是通知的意思,
- 概述主要用于Java线程里指定时间或周期运行任务。Timer是线程安全的,但不提供实时性(real-time)保证。构造函数Timer()默
- JAVA 静态代理模式代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。代理模式说白了就是“真实对象”的代表,在访问对象
- 概述 这是一个自定义色盘,根据点,直线和圆的几何学加上hsv颜色模型完成技术点几何:圆的标准方程式:(x-a)²
- 话不多说,请看下面//C# 代码int year = DateTime.Now.Year;int month = DateTime.Now.
- 当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享。各个对象都拥有类中每一个普通数据成员的副
- namespace PadWebServices.Model{ public static class DataTa
- 一、在pom.xml中配置jetty插件: <build> <plugins> <p
- 循环依赖定义循环依赖就 循环引用,就是两个或多个 bean 相互之间的持有对方,比如 CircleA 引用 CircleB , Circle