wordpress 换空间 换域名,上海seo顾问推推蛙,小程序制作报价单,网站做三层结构Lambda Lambda表达式是一种匿名函数#xff0c;Lambda表达式通常以箭头“”分隔左侧的输入和右侧的输出。 (parameter_list) { statement_block } parameter_list 是由一个或多个参数组成的逗号分隔列表#xff0c;每个参数都包括类型和名称#xff0c;可以为空。… Lambda Lambda表达式是一种匿名函数Lambda表达式通常以箭头“”分隔左侧的输入和右侧的输出。 (parameter_list) { statement_block } parameter_list 是由一个或多个参数组成的逗号分隔列表每个参数都包括类型和名称可以为空。 如果只有一个参数只写参数名即可不用圆括号。 Funcint, int add y 1 y; 如果是多个参数把参数放在圆括号内。 Funcint, int,int add (x,y) x y; statement_block 是Lambda表达式的主体。statement_block表示一段代码块它可以包含多个语句多个语句使用大括号包裹。 如果Lambda表达式只有一句语句statement_block不需要花括号和return语句。 Funcint, int,int add (x,y) x y; 如果是含有多条语句必须加上花括号和return语句。 Funcint, int,int add (x,y) { X x1; Y y1; Return xy; } 常用的方法 Where Where方法是IEnumerableT接口的扩展方法它筛选序列中满足指定条件的元素返回满足条件的元素序列. Listint numbers new Listint { 1, 2, 3, 4, 5 }; var oddNumbers numbers.Where(x x % 2 ! 0); Select 它将序列中的每个元素投影到新的形式返回投影后的元素序列. Listint numbers new Listint { 1, 2, 3, 4, 5 }; var squaredNumbers numbers.Select(x x * x); Orderby 按照指定的键对序列中的元素进行排序. Liststring words new Liststring { apple, banana, cherry, date }; var sortedWords words.OrderBy(x x.Length); GroupBy 根据指定的键对序列中的元素进行分组. Liststring words new Liststring { apple, banana, cherry, date }; var groupedWords words.GroupBy(x x[0]); Lambda表达式中的闭包 闭包是指一个函数能够访问并操作在它的外部作用域中定义的变量。在Lambda表达式中可以使用闭包来访问外部作用域中的变量. int x 5; Funcint, int add y x y; Console.WriteLine(add(3)); 委托 委托是一种引用类型表示对具有特定参数列表和返回类型的方法的引用。在实例化委托时你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 委托可以链接在一起一次性调用多个方法你可以通过委托实例调用方法。委托用于将方法作为参数传递给其他方法可用于定义回调方法可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。该方法可以是静态方法也可以是实例方法。 此灵活性意味着你可以通过编程方式来更改方法调用还可以向现有类中插入新代码。 委托类型派生自 .NET 中的 Delegate 类。 委托类型是密封的它们不能派生自 Delegate也不能从其派生出自定义类 简单地说委托类似c的函数指针。 如何使用委托 委托是一种引用类型虽然在定义委托时与方法有些相似但不能将其称为方法。 委托在使用时遵循三步走的原则即定义声明委托、实例化委托以及调用委托。 public class ShowTest { public delegate void ShowDelegate(string strText); public Actionstring action; public void Show(string strText) { Console.WriteLine(strText); } public void test() { ShowDelegate showDelegate1 new ShowDelegate(Show); ShowDelegate showDelegate2 Show; ShowDelegate showDelegate3 delegate (string strText) { Console.WriteLine(strText); }; ShowDelegate showDelegate4 (string strText) { Console.WriteLine(strText); }; string Text hello; showDelegate1(Text); showDelegate2.Invoke(Text); action Show; action(Text); } } 声明委托 修饰符 delegate 返回值类型 委托名 ( 参数列表 ); 如public delegate void ShowDelegate (); 在命名空间内但不在类内 实例化委托 方式1通过new 创建委托实例 必须传入一个方法作为参数否则会报错因为委托内部的构造函数需求传递一个方法作为参数。 委托名 委托对象名 new 委托名 ( 方法名 ); 委托中传递的方法名既可以是静态方法的名称也可以是实例方法的名称。需要注意的是在委托中所写的方法名必须与委托定义时的返回值类型和参数列表相同。 ShowDelegate showDelegate1 new ShowDelegate(Show); 方式2使用赋值的方式 ShowDelegate showDelegate2 Show; 方式3匿名委托 ShowDelegate showDelegate3 delegate (string strText) { Console.WriteLine(strText); }; 方式4Lambda ShowDelegate showDelegate4 (string strText) { Console.WriteLine(strText); }; 调用委托 方式1直接调用委托的变量 showDelegate1(Text); 方式2invoke() showDelegate2.Invoke(Text); 匿名委托 匿名方法的意义在于快速方便的实例化委托不用定义具体的方法来关联委托就是临时定义个方法处理逻辑与委托相关联。只是在实例化委托按照下面的格式处理。 委托类型 变量名 delegate( 形参 ) { 逻辑处理语句 }; Funcstring, string dele delegate (string strpa) { string strq sa; return strq; }; dele(str); 缺点不能在其他地方被调用即不具有复用性。 而且匿名方法会将自动形成闭包。当一个函数这里称为外部函数包含对另一个函数内部函数的调用时或内部函数使用了外部函数的变量时都会形成闭包。 闭包 在C#中我们可以使用Lambda来实现闭包闭包本质是一个对象(编译后,但使用上它和方法一致。使用闭包我们就可以实现拥有私有状态的函数! 定义我们把在Lambda表达式(或匿名方法)中所引用的外部变量称为捕获变量。而捕获变量的表达式就称为闭包。 捕获变量捕获的变量会在真正调用委托时“赋值”而不是在捕获时“赋值”即总是使用捕获变量的最新的值。 作用内层的函数可以引用包含在它外层的函数的变量即使外层函数的执行已经终止。 public class ShowTest { public Actionstring action1; ShowTest() { string tt qq; action1 (string str) { Console.WriteLine(tt str); }; } public void test() { string Text hello; action1(Text); } } 泛型委托 由于单独定义委托和事件比较繁琐而且比较冗余因此C#2.0提供了Action 和Func两个泛型委托不用单独申明拿来就可以用。 ActionT 1Action 表示无参无返回值的委托 2Actionint,string 表示有参无返回值的泛型委托最多可入参16个 3使用Action 就可以囊括所有无返回值委托可以说Action事对无返回值委托的进一步包装 public class ShowTest { public Actionstring action; public void Show(string strText) { Console.WriteLine(strText); } public void test() { action Show; //或者 通过new 创建委托实例 委托名 委托对象名 new 委托名 ( 方法名 ); action new Actionstring(Show); action(Text); } } FuncT 1Func 表示有返回值的委托必须有返回值 2Func可以无参数也可以有参数最多16个参数最后一个表示返回值且只有一个 3使用方法同delegate,Func不过是对所有的有返回值的数据进行了一个包装 public class ShowTest { public Funcint, int,int addfunc; public int add(int a,int b) { return a b; } public void test() { addfunc add; int nRet addfunc(1, 2); } } 多播委托 通过绑定多个方法到这个委托从而形成委托链。执行委托的时候按照添加方法的顺序依次去执行方法 注意 1.action.BeginInvoke();会开启一个新的线程去执行委托注册有多个方法的委托不能使用BeginInvoke。 2.注册有多个方法的委托想要开启新线程去执行委托可以通过action.GetInvocationList()获取到所有的委托然后循环每个方法执行的时候可以BeginInvoke 3.使用多播委托的时候可能会遇到一个问题就是委托链的第一个方法报错了导致后面的注册的方法都无法调用。解决办法使用GetInvocationList 按照调用顺序返回此多播委托的调用列表。 public class ShowTest { public delegate void BuySomethingDelegate(); public void BuyWater() { Console.WriteLine(买水); } public void BuyKFC() { Console.WriteLine(买肯德基); } public void BuyHotDog() { Console.WriteLine(买热狗); } public void test() { BuySomethingDelegate bsd new BuySomethingDelegate(BuyWater); bsd BuyHotDog; bsd BuyKFC; bsd - BuyHotDog; Delegate[] delegateArr bsd.GetInvocationList(); foreach (BuySomethingDelegate item in delegateArr) { try { item.Invoke(); } catch (Exception) { Console.WriteLine(${item.Method.Name}方法报错了); } } } } 延伸 Invoke Invoke的本质只是一个方法方法一定是要通过对象来调用的。 Control的Invoke、Delegate的Invoke 也就是说Invoke前面要么是一个控件要么是一个委托对象。 Control的Invoke public object Invoke(Delegate method); public object Invoke(Delegate method, params object[] args); Control的Invoke一般用于解决跨线程访问的问题。即在子线程中让主线程的控件调用Invoke函数从而操作主线程的UI空间。 使用Invoke完成一个委托方法的封送就类似于使用SendMessage会阻塞。 Delegate的Invoke 目的作用就是执行委托。Delegate的Invoke其实就是从线程池中调用委托方法执行Invoke是同步的方式会卡住调用它的UI线程。 BeginInvoke 使用BeginInvoke方法封送一个委托方法类似于使用PostMessage进行通信这是一个异步方法。 Control的BeginInvoke Control类上的异步调用BeginInvoke并没有开辟新的线程完成委托任务而是让界面控件的所属线程完成委托任务的。还是在同一线程执行 Delegate的BeginInvoke Delegate.BeginInvoke方法是从ThreadPool中取出的一个线程来执行这个方法以获得异步的执行效果。不同的线程执行 事件
事件本质上来讲是一种特殊的多播委托。
作用C# 中常常会使用事件来实现线程之间的通信。
在 C# 中类或对象可以通过事件向其他类或对象通知发生的相关事情。这种模式通常称为发布订阅模型发送或引发事件的类称为“发布者”接收或处理事件的类称为“订阅者”。所以事件主要用于发布订阅者模式即设计模式中的观察者模式。
好处就是解耦
发布者 一个创建了事件和委托定义的对象同时也包含了事件和委托之间的联系与具体行为。发布者的任务就是执行这些事件并通知程序中的其它对象。
订阅者 一个接收事件并提供事件处理程序的对象。订阅者中的方法事件处理程序用于分配给发布者中的委托。 简单的来说发布者确定何时引发事件而订阅者确定对事件作出何种响应。
using System; 事件的声明
事件的本质还是委托所以要声明一个事件之前必须先声明一个相对应的委托。
public delegate void PubDelegate();
在 C# 中事件需要使用关键字 event
Access Specifier event Delegate Event Name
public event PubDelegate PubEvent; 事件的使用范围
仅可以从声明事件的类或派生类或结构发布服务器类中对其进行调用。 // 发布者类
public class PublisherClass
{ // 和事件搭配的委托 public delegate void PubDelegate(); // 定义事件 public event PubDelegate PubEvent; // 编写处理事件的具体逻辑 public void EventHandling() { if (PubEvent null) { Console.WriteLine(需要注册事件的啊); } else { // 执行注册的事件 PubEvent(); } }
} // 订阅者类
public class SubscriberClass
{ public void printout() { Console.WriteLine(执行了订阅者类中的事件。); Console.ReadLine(); }
} public class Program
{ static void Main() { // 实例化对象 PublisherClass p new PublisherClass(); SubscriberClass s new SubscriberClass(); // 执行事件 p.EventHandling(); // 注册事件 p.PubEvent new PublisherClass.PubDelegate(s.printout); // 执行事件 p.EventHandling(); }
} 事件委托之EventHandler
想直接用事件且懒得去声明委托,这时候微软给我提供了一个委托叫EventHandler,主要是给事件服务的。
事件的声明就是
public event EventHandler 事件名; public delegate void EventHandler(object sender, EventArgs e);
object sender一般写this
EventArgs e:事件参数,如果无参数就写成EventArgs.Empty
using System;
namespace CSharplearn
{
class Program
{
static void Main(string[] args)
{
Trigger trigger new Trigger();
trigger.TrigMethod(); }
}
class Trigger
{
public event EventHandler TrigEvent;
public void TrigMethod()
{
TrigEvent Logic.Printer;
TrigEvent(this,EventArgs.Empty);
}
}
class Logic
{
public static void Printer(object sender,EventArgs e)
{
Console.WriteLine(Hello World);
}
}
} 泛型兄弟长这样
public delegate void EventHandlerTEventArgs(object sender, TEventArgs e); using System;
namespace CSharplearn
{
class Program
{
static void Main(string[] args)
{
Trigger trigger new Trigger();
trigger.TrigMethod();
}
}
class Trigger
{
public event EventHandlerMyEventArgs TrigEvent;
public void TrigMethod()
{
MyEventArgs myArgs new MyEventArgs();
myArgs.String Hello Space;
TrigEvent Logic.Printer;
TrigEvent(this, myArgs);
//或者是 TrigEvent?.Invoke(this, myArgs);
}
}
class Logic
{
public static void Printer(object sender,MyEventArgs e)
{
Console.WriteLine(e.String);
}
}
public class MyEventArgs : EventArgs
{
public string String;
}
} 事件与委托的异同
相同点
事件其实是一个多播委托本质上是一样的。
不同点
可调用位置不同事件只能在声明事件的类中才能调用而委托无论是在类的内部还是外部都可以调用。
可使用符号不同事件只能使用 和 - 符号来订阅和取消订阅但是委托不仅可以使用 和 - 符号还可以使用 符号进行方法分配。