C# 委托、事件,lamda表达式

C#委托与事件详解
本文详细介绍了C#中的委托和事件概念,包括委托的基本使用、协变与逆变、泛型委托、事件的由来及其封装性,以及lambda表达式的应用。通过丰富的示例代码帮助读者更好地理解和掌握。

1. 委托Delegate

     C#中的Delegate对应于C中的指针,但是又有所不同C中的指针既可以指向方法,又可以指向变量,并且可以进行类型转换,

C中的指针实际上就是内存地址变量,他是可以直接操作内存的,通过内存地址直接访问变量,直接调用方法。

     而C#中的Delegate是强类型的,也就是说在声明委托时就已经指定了该变量只能指向具有特定参数,以及返回值的方法。

    使用delegate就可以直接建立任何名称的委托类型,当进行系统编译时,系统就会自动生成此类型。您可以使用delegate void MyDelegate() 方式建立一个委托类,并使用ILDASM.exe观察其成员。由ILDASM.exe 中可以看到,它继承了System.MulticastDelegate类,

并自动生成BeginInvoke、EndInvoke、Invoke 等三个常用方法。

image

Invoke 方法是用于同步调用委托对象的对应方法,而BeginInvoke、EndInvoke是用于以异步方式调用对应方法的。

1
2
3
4
5
6
7
8
public class MyDelegate:MulticastDelegate
      {
          //同步调用委托方法
          public virtual void Invoke();
          //异步调用委托方法
          public virtual IAsyncResult BeginInvoke(AsyncCallback callback,object state);
          public virtual void EndInvoke(IAsyncResult result);
      }

MulticastDelegate是System.Delegate的子类,它是一个特殊类,编译器和其他工具可以从此类派生,但是自定义类不能显式地从此类进行派生。它支持多路广播委托,并拥有一个带有链接的委托列表,在调用多路广播委托时,系统将按照调用列表中的委托出现顺序来同步调用这些委托。

MulticastDelegate具有两个常用属性:Method、Target。其中Method 用于获取委托所表示的方法Target 用于获取当前调用的类实例。

 

1.1 委托的使用

当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直接绑定此方法。使用myDelegate.Invoke(string message),就能显式调用委托方法。但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。

无返回值的委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Program
     {
         delegate void MyDelegate(string message);
 
         public class Example
         {
             public void Method(string message)
             {
                 MessageBox.Show(message);
             }
         }
 
         static void Main(string[] args)
         {
             Example example= new Example();
             MyDelegate myDelegate= new MyDelegate(example.Method);
             myDelegate( "Hello World" );
             Console.ReadKey();
         }
     }

有返回值的委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Program
     {
         delegate string MyDelegate(string message);
 
         public class Example
         {
             public string Method(string name)
             {
                 return "Hello " + name;
             }
         }
 
         static void Main(string[] args)
         {
             Example example= new Example();
             //绑定委托方法
             MyDelegate myDelegate= new MyDelegate(example.Method);
             //调用委托,获取返回值
             string message = myDelegate("Leslie");
             Console.WriteLine(message);
             Console.ReadKey();
         }
     }

 

多路广播委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
delegate double MyDelegate(double message);
 
         public class Price
         {
             public double Ordinary(double price)
             {
                 double price1 = 0.95 * price;
                 Console.WriteLine( "Ordinary Price : " +price1);
                 return price1;
             }
 
             public double Favourable(double price)
             {
                 double price1 = 0.85 * price;
                 Console.WriteLine( "Favourable Price : " + price1);
                 return price1;
             }
 
             static void Main(string[] args)
             {
                 Price price = new Price();
                 //绑定Ordinary方法
                 MyDelegate myDelegate = new MyDelegate(price.Ordinary);
                 //绑定Favourable方法
                 myDelegate += new MyDelegate(price.Favourable);
                 //调用委托
                 Console.WriteLine( "Current Price : " + myDelegate(100));
                 Console.ReadKey();
             }
         }

输出

image

 

1.2 委托的协变与逆变

     前面已经说过,委托是强类型的方法指针,但是在面对具有继承关系类型的参数、或者返回值时,委托是如何处理的呢。

协变(返回值类型具有继承关系的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Worker
      {.......}
      public class Manager:Worker
      {.......}
 
       class Program
      {
          public delegate Worker GetWorkerHandler(int id);
          //在 Framework2.0 以上,委托 GetWorkerHandler 可绑定 GetWorker 与 GetManager 两个方法 
          public static Worker GetWorker(int id)
          {
              Worker worker = new Worker();
              return worker;
          }
 
          public static Manager GetManager(int id)
          {
              Manager manager = new Manager();
              return manager;
          }
 
         static void Main(string[] args)
         {
             GetWorkerHandler workerHandler = new GetWorkerHandler(GetWorker);
             Worker worker=workerHandler(1);
             GetWorkerHandler managerHandler = new GetWorkerHandler(GetManager);
             Manager manager = managerHandler(2) as Manager;
             Console.ReadKey();
         }
      }

委托 GetWorkerHandler 可以绑定 GetWorker 与 GetManager 两个方法

 

逆变

委托逆变,是指委托方法的参数同样可以接收 “继承” 这个传统规则。像下面的例子,以 object 为参数的委托,可以接受任何 object 子类的对象作为参数。最后可以在处理方法中使用 is 对输入数据的类型进行判断,分别处理对不同的类型的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
     {
         public delegate void Handler(object obj);
 
         public static void GetMessage(object message)
         {
             if (message is string)
                 Console.WriteLine( "His name is : " + message.ToString());
             if (message is int)
                 Console.WriteLine( "His age is : " + message.ToString());
         }
 
         static void Main(string[] args)
         {
             Handler handler = new Handler(GetMessage);
             handler(29);
             Console.ReadKey();
         }
    }

 

注意委托与其绑定方法的参数必须一至,即当 Handler 所输入的参数为 object 类型,其绑定方法 GetMessage 的参数也必须为 object 。否则,即使绑定方法的参数为 object 的子类,系统也无法辨认。

 

大家可能注意到了,这个委托方法GetMessage的实现不是那么优雅,于是泛型委托应运而生。

 

class Program { public delegate void Handler<T>(T obj); public static void GetWorkerWages(Worker worker) { Console.WriteLine("Worker's total wages is " + worker.Wages); } public static void GetManagerWages(Manager manager) { Console.WriteLine("Manager's total wages is "+manager.Wages); } static void Main(string[] args) { Handler<Worker> workerHander = new Handler<Worker>(GetWorkerWages); Worker worker = new Worker(); worker.Wages = 3000; workerHander(worker); Handler<Manager> managerHandler = new Handler<Manager>(GetManagerWages); Manager manager = new Manager(); manager.Wages = 4500; managerHandler(manager); Console.ReadKey(); } }

 

2. event事件的由来

事件是特殊的委托,他为委托提供了封装性,一方面允许从类的外部增加,删除绑定方法,另一方面又不允许从类的外部来触发委托所绑定了方法。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public delegate double PriceHandler();
 
     public class PriceManager
     {
         public PriceHandler GetPriceHandler;
 
         //委托处理,当价格高于100元按8.8折计算,其他按原价计算
         public double GetPrice()
         {
             if (GetPriceHandler.GetInvocationList().Count() > 0)
             {
                 if (GetPriceHandler() > 100)
                     return GetPriceHandler()*0.88;
                 else
                     return GetPriceHandler();
             }
             return -1;
         }
     }
 
     class Program
     {
         static void Main(string[] args)
         {
             PriceManager priceManager = new PriceManager();
            
             //调用priceManager的GetPrice方法获取价格
             //直接调用委托的Invoke获取价格,两者进行比较
             priceManager.GetPriceHandler = new PriceHandler(ComputerPrice);
             Console.WriteLine( string .Format( "GetPrice\n  Computer's price is {0}!" ,
                 priceManager.GetPrice()));
             Console.WriteLine( string .Format( "Invoke\n  Computer's price is {0}!" ,
                 priceManager.GetPriceHandler.Invoke()));
            
             Console.WriteLine();
            
             priceManager.GetPriceHandler = new PriceHandler(BookPrice);
             Console.WriteLine( string .Format( "GetPrice\n  Book's price is {0}!" ,
                 priceManager.GetPrice()));
             Console.WriteLine( string .Format( "Invoke\n  Book's price is {0}!" ,
                 priceManager.GetPriceHandler.Invoke()));
            
             Console.ReadKey();
         }
         //书本价格为98元
         public static double BookPrice()
         {
             return 98.0;
         }
         //计算机价格为8800元
         public static double ComputerPrice()
         {
             return 8800.0;
         }
     }

以上代码实现了对于100元以上商品的的88折处理。一方面为了给GetPriceHandler绑定方法就必须将委托声明为public,但是一旦声明为public

就可以在类外部直接通过Invoke来调用该委托所绑定的方法,而产生我们不需要的结果。

image

 

当然我们可以将GetPriceHandler声明为private并且通过public 的addHandler,removeHandler来消除委托public的副作用,但是C#提供了更加优雅的方法:

那就是event关键字。

 

事件(event)可被视作为一种特别的委托,它为委托对象隐式地建立起add_XXX、remove_XXX 两个方法,用作注册与注销事件的处理方法。而且事件对应的变量成员将会被视为 private 变量,外界无法超越事件所在对象直接访问它们,这使事件具备良好的封装性,而且免除了add_XXX、remove_XXX等繁琐的代码。

1
2
3
4
5
public class EventTest
     {
         public delegate void MyDelegate();
         public event MyDelegate MyEvent;
     }

 

观察事件的编译过程可知,在编译的时候,系统为 MyEvent 事件自动建立add_MyEvent、remove_MyEvent 方法。

image

 

事件能通过+=和-=两个方式注册或者注销对其处理的方法,使用+=与-=操作符的时候,系统会自动调用对应的 add_XXX、remove_XXX 进行处理。 值得留意,在PersonManager类的Execute方法中,如果 MyEvent 绑定的处理方法不为空,即可使用MyEvent(string)引发事件。但如果在外界的 main 方法中直接使用 personManager.MyEvent (string) 来引发事件,系统将引发错误报告。这正是因为事件具备了良好的封装性,使外界不能超越事件所在的对象访问其变量成员。

 

注意在事件所处的对象之外,事件只能出现在+=,-=的左方。

 

public delegate void MyDelegate(string name);      public class PersonManager      {          public event MyDelegate MyEvent;          //执行事件          public void Execute(string name)          {              if (MyEvent != null)                  MyEvent(name);          }      }      class Program      {          static void Main(string[] args)          {              PersonManager personManager = new PersonManager();              //绑定事件处理方法              personManager.MyEvent += new MyDelegate(GetName);              personManager.Execute("Leslie");              Console.ReadKey();          }          public static void GetName(string name)          {              Console.WriteLine("My name is " + name);          }      }

 

在绑定事件处理方法的时候,事件出现在+=、-= 操作符的左边,对应的委托对象出现在+=、-= 操作符的右边。对应以上例子,事件提供了更简单的绑定方式,只需要在+=、-= 操作符的右方写上方法名称,系统就能自动辩认。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public delegate void MyDelegate(string name);
 
     public class PersonManager
     {
         public event MyDelegate MyEvent;
         .........
     }
 
     class Program
     {
         static void Main(string[] args)
         {
             PersonManager personManager = new PersonManager();
             //绑定事件处理方法
             personManager.MyEvent += GetName;
             .............
         }
 
         public static void GetName(string name)
         {.........}
    }

如果觉得编写 GetName 方法过于麻烦,你还可以使用匿名方法绑定事件的处理。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public delegate void MyDelegate(string name);
 
     public class PersonManager
     {
         public event MyDelegate MyEvent;
 
         //执行事件
         public void Execute(string name)
         {
             if (MyEvent != null)
                 MyEvent(name);
         }
 
         static void Main(string[] args)
         {
             PersonManager personManager = new PersonManager();
             //使用匿名方法绑定事件的处理
             personManager.MyEvent += delegate ( string name){
                 Console.WriteLine( "My name is " +name);
             };
             personManager.Execute( "Leslie" );
             Console.ReadKey();
         }
     }
1
 

3. lambda表达式

 

在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 起,系统开始支持匿名方法。 通过匿名方法,可以直接把一段代码绑定给事件,因此减少了实例化委托所需的编码系统开销。 而在 Framework 3.0 开始,Lambda 表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。总体来说,Lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。

使用匿名方法

1
2
3
4
5
6
7
static void Main(string[] args)
         {
             Button btn = new Button();
             btn.Click+= delegate ( object obj,EventArgs e){
                 MessageBox.Show( "Hello World !" );
             };
         }

使用lambda表达式

1
2
3
4
5
6
7
static void Main(string[] args)
         {
             Button btn = new Button();
             btn.Click+=( object obj,EventArgs e)=>{
                 MessageBox.Show( "Hello World !" );
             };
         }

 

3.1常用泛型委托

public delegate bool Predicate<T>(T obj)

它是一个返回bool的泛型委托,能接受一个任意类型的对象作为参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Program
     {
         static void Main(string[] args)
         {
             List<Person> list = GetList();
             //绑定查询条件
             Predicate<Person> predicate = new Predicate<Person>(Match);
             List<Person> result = list.FindAll(predicate);
             Console.WriteLine(“Person count is : ” + result.Count);
             Console.ReadKey();
         }
         //模拟源数据
         static List<Person> GetList()
         {
             var personList = new List<Person>();
             var person1 = new Person(1,"Leslie",29);
             personList.Add(person1);
             ........
             return personList;
         }
         //查询条件
         static bool Match(Person person)
         {
             return person.Age <= 30;
         }
     }
 
     public class Person
     {
         public Person(int id, string name, int age)
         {
             ID = id;
             Name = name;
             Age = age;
         }
 
         public int ID
         { get ; set ; }
         public string Name
         { get ; set ; }
         public int Age
         { get ; set ; }
     }
1
 

Action<T> 的使用方式与 Predicate<T> 相似,不同之处在于 Predicate<T> 返回值为 bool ,  Action<T> 的返回值为 void。 Action 支持0~16个参数,可以按需求任意使用。

public delegate void Action()

public delegate void Action<T1>(T1 obj1) public delegate void Action<T1,T2> (T1 obj1, T2 obj2) public delegate void Action<T1,T2,T3> (T1 obj1, T2 obj2,T3 obj3) ............ public delegate void Action<T1,T2,T3,......,T16> (T1 obj1, T2 obj2,T3 obj3,......,T16 obj16)

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
         {
             Action< string > action=ShowMessage;
             action( "Hello World" );
             Console.ReadKey();
         }
 
         static void ShowMessage(string message)
         {
             MessageBox.Show(message);
         }
1
 

委托 Func 与 Action 相似,同样支持 0~16 个参数,不同之处在于Func 必须具有返回值

public delegate TResult Func<TResult>()

public delegate TResult Func<T1,TResult>(T1 obj1)

public delegate TResult Func<T1,T2,TResult>(T1 obj1,T2 obj2)

public delegate TResult Func<T1,T2,T3,TResult>(T1 obj1,T2 obj2,T3 obj3)

............

public delegate TResult Func<T1,T2,T3,......,T16,TResult>(T1 obj1,T2 obj2,T3 obj3,......,T16 obj16)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static void Main(string[] args)
         {
             Func< double , bool , double > func = Account;
             double result=func(1000, true);
             Console.WriteLine( "Result is : " +result);
             Console.ReadKey();
         }
 
         static double Account(double a,bool condition)
         {
             if (condition)
                 return a * 1.5;
             else
                 return a * 2;
         }

 

 

3.2 lambda表达式

Lambda 的表达式的编写格式如下:

     x=> x * 1.5

当中 “ => ” 是 Lambda 表达式的操作符,在左边用作定义一个参数列表,右边可以操作这些参数。

例子一, 先把 int x 设置 1000,通过 Action 把表达式定义为 x=x+500 ,最后通过 Invoke 激发委托。

static void Main(string[] args)          {              int x = 1000;              Action action = () => x = x + 500;              action.Invoke();              Console.WriteLine("Result is : " + x);              Console.ReadKey();          }

 

例子二,通过 Action<int> 把表达式定义 x=x+500, 到最后输入参数1000,得到的结果与例子一相同。 注意,此处Lambda表达式定义的操作使用 { } 括弧包括在一起,里面可以包含一系列的操作。

static void Main(string[] args)          {              Action<int> action = (x) =>              {                  x = x + 500;                  Console.WriteLine("Result is : " + x);              };              action.Invoke(1000);              Console.ReadKey();          }

转载于:https://www.cnblogs.com/FinleyJiang/p/7602037.html

<think> 首先,用户的问题是:“我想了解C#中lambda表达式的相关信息 请问C#中lambda表达式的使用、特点和示例”。这建立在之前的系统指令上。 回顾系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户提供了引用: - 引用[1]:关于C# Lambda表达式的简介,包括语法和内联特性。 - 引用[2]:强调Lambda表达式的强大性,在LINQ和异步编程中的作用。 - 引用[3]:定义Lambda表达式,与匿名方法的比较,核心概念。 - 引用[4]:示例Lambda表达式带参数。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,这是第一个用户消息。之前的系统指令是初始设置,没有上一次的用户问题。所以,我应该基于当前问题和引用回应。 关键点: - 用户想了解C#中lambda表达式的使用、特点和示例。 - 引用提供了信息,我需要整合这些。 回答结构: 1. **清晰的结构**:介绍、使用、特点、示例。 2. **使用中文**:整个回答用中文。 3. **数学表达式**:如果有数学相关的,用LaTeX,但lambda表达式在编程中,可能不涉及数学公式。C#的lambda表达式是编程概念,不是数学表达式。所以,可能不需要LaTeX,除非有类似的东西。但指令说所有行内数学表达式必须用$...$,所以我需要检查是否有数学部分。在示例中,如果有数学操作,可以用LaTeX。 4. **引用标识**:在回答中,如果引用提供的段落,末尾添加[^1]等。用户提供了引用内容,所以在回答中用到时添加引用标识。 5. **生成相关问题**:在回答末尾,生成相关问题。 集成引用: - 引用[1]:Lambda简化代码和提高可读性,语法和内联特性。 - 引用[2]:在LINQ和异步编程中的作用。 - 引用[3]:更简洁的匿名函数形式。 - 引用[4]:带参数的示例。 回答大纲: - **介绍**:简述Lambda表达式是什么。 - **特点**:基于引用,列出特性如简洁、灵活、可读性强等。 - **使用**:说明如何使用,包括语法和场景(如LINQ)。 - **示例**:给出代码示例,基于引用[4]。 生成相关问题:在末尾添加“§§相关问题§§”部分,列出几个相关问题。 确保回答真实可靠:作为AI,基于一般知识,但参考提供的引用。 最终回答结构: 1. 开头介绍。 2. 详细解释特点和用法。 3. 示例代码。 4. 相关问题。 </think> ### C#中的Lambda表达式C#编程语言中,Lambda表达式是一种强大的函数式编程特性,它允许以内联方式定义匿名函数(即没有显式名称的函数)。Lambda表达式通过简化委托表达式树的编写,显著提升代码的简洁性和可读性。它广泛应用于事件处理、LINQ查询、异步编程等场景中。根据引用内容,我将从使用、特点和示例三个方面详细解释,并结合真实示例进行说明。回答基于C#标准实践和提供的引用信息[^1][^2][^3]。 #### 1. Lambda表达式的特点 Lambda表达式的主要特点源于其语法简洁性和灵活性: - **简洁性**:相较于传统的匿名方法,Lambda表达式语法更精简,减少了冗余代码。例如,它可以直接内联定义函数逻辑,无需显式声明委托类型。这使得代码更易于维护和阅读。Lambda表达式通过其内联特性实现简洁化,尤其在处理简单逻辑时优势明显[^1][^3]。 - **灵活性**:Lambda表达式支持多种形式,包括带参数和无参数表达式。它可以直接用于委托表达式树(Expression Trees)以及集合操作中,与LINQ(Language Integrated Query)无缝集成,实现数据查询和转换。此外,它在异步编程(如Task.Run)中发挥重要作用,提升开发效率[^2][^3]。 - **可读性强**:通过=>运算符(lambda运算符),Lambda表达式将输入参数与表达式主体分隔开,使逻辑更直观。例如,(a, b) => a + b 清晰地表达了加法操作。这种结构有助于团队协作和代码维护[^1][^4]。 - **匿名性**:作为匿名函数,Lambda表达式不绑定到特定方法名,而是在使用时动态定义,适用于一次性的函数逻辑。这在事件处理或回调函数中尤为有用[^3]。 #### 2. Lambda表达式的使用 Lambda表达式的语法格式为:`(参数列表) => 表达式或语句块`。其中: - **参数列表**:可以是零个或多个参数,类似于方法参数。如果只有一个参数,括号可省略;多个参数需用逗号分隔。 - **表达式主体**:如果主体是单个表达式,它将自动返回值;如果是语句块(用{}包裹),需显式使用return语句。 Lambda表达式主要用于以下场景: - **委托赋值**:将Lambda表达式赋值给委托类型(如Func<T>或Action<T>),替代匿名方法。例如,在事件处理中定义回调函数[^1][^4]。 - **LINQ查询**:在集合操作中,Lambda表达式常用于Where、Select等扩展方法,实现数据过滤和投影。这提高了查询代码的可读性[^2]。 - **表达式树**:Lambda表达式可转换为表达式树(Expression<TDelegate>),用于动态生成代码或ORM框架(如Entity Framework),实现延迟执行[^3]。 - **异步编程**:结合async/await,Lambda表达式简化了异步任务的定义,如在Task.Run中内联指定操作[^2]。 使用注意事项: - Lambda表达式在编译时生成委托表达式树,性能高效。 - 避免过度嵌套Lambda表达式,以免降低可读性。 - 在闭包中,Lambda表达式可以捕获外部变量,但需注意变量作用域问题(如可能导致的内存泄漏)。 #### 3. Lambda表达式示例 以下是基于引用[^4]的示例代码,展示Lambda表达式的实际用法。示例使用C#控制台应用程序,覆盖常见场景。 **示例1:基本加法Lambda(带参数)** 这是一个简单的Lambda表达式,用于定义加法操作并赋值给Func委托。 ```csharp // 定义Lambda表达式:两个参数相加 Func<int, int, int> add = (a, b) => a + b; int result = add(3, 4); // 调用Lambda表达式 Console.WriteLine(result); // 输出:7 ``` - **说明**:这里的`(a, b) => a + b`是一个Lambda表达式,它接受两个整数参数并返回它们的和。=>运算符分隔参数和表达式主体,主体是单行表达式,自动返回值。 **示例2:LINQ查询中的应用** Lambda表达式在LINQ中广泛用于集合过滤和转换。 ```csharp using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; // 使用Lambda表达式过滤偶数 var evenNumbers = numbers.Where(n => n % 2 == 0); // 使用Lambda表达式计算平方 var squares = numbers.Select(x => x * x); Console.WriteLine("偶数: " + string.Join(", ", evenNumbers)); // 输出:2, 4 Console.WriteLine("平方: " + string.Join(", ", squares)); // 输出:1, 4, 9, 16, 25 } } ``` - **说明**:`n => n % 2 == 0`是Lambda表达式,用于Where方法过滤集合;`x => x * x`用于Select方法映射元素。这些表达式简化了集合操作,提升了代码可读性[^2]。 **示例3:异步任务中的Lambda** Lambda表达式在异步编程中定义任务逻辑。 ```csharp using System; using System.Threading.Tasks; class Program { static async Task Main() { // 使用Lambda表达式定义异步任务 await Task.Run(() => { Console.WriteLine("异步任务执行中..."); // 模拟耗时操作 Task.Delay(1000).Wait(); Console.WriteLine("任务完成!"); }); } } ``` - **说明**:这里的`() => { ... }`是一个无参数的Lambda表达式,作为Task.Run的输入。表达式主体是语句块,包含多条语句,适用于复杂逻辑[^2]。 **示例4:事件处理(简化版)** Lambda表达式可用于事件订阅。 ```csharp using System; class Button { public event EventHandler Click; public void SimulateClick() { Click?.Invoke(this, EventArgs.Empty); } } class Program { static void Main() { Button button = new Button(); // 使用Lambda表达式订阅事件 button.Click += (sender, e) => Console.WriteLine("按钮被点击了!"); button.SimulateClick(); // 输出:按钮被点击了! } } ``` - **说明**:`(sender, e) => Console.WriteLine("按钮被点击了!")`是一个Lambda表达式,替代了传统的事件处理程序方法,使代码更紧凑[^1]。 综上所述,Lambda表达式C#核心特性之一,通过简洁、灵活的语法提升代码质量。合理使用它,可以简化开发流程,特别是在现代C#项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值