当前位置: 首页 > article >正文

C# 委托和事件(Lambda表达式)

回调(callback)函数是Windows编程的一个重要部分。C或C++编程背景,在许多Windows API中使用过回调。VB添加AddressOf关键字后,开发人员就可以利用以前一度受到限制的API。回调函数实际上是方法调用的指针也称为函数指针。.NET以委托的形式实现函数指针的概念。C中函数指针只不过是一个指向存储单元的指针,无法说出这个指针实际指向什么,像参数和返回类型等更不知晓。

Lambda表达式

从C# 3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式。只要有委托参数类型,就可以使用Lambda表达式。
Lambda表达式的语法比匿名方法简单。如果所调用的方法有参数,且不需要参数,匿名方法的语法就比较简单。

using System;
using System.Collections.Generic;

SimpleDemos();
ClosureWithModification();
ClosureWithForEach();

void SimpleDemos()
{
    Console.WriteLine(nameof(SimpleDemos));
    Func<string, string> oneParam = s => $"change uppercase {s.ToUpper()}";
    Console.WriteLine(oneParam("test"));

    Func<double, double, double> twoParams = (x, y) => x * y;
    Console.WriteLine(twoParams(3, 2));

    Func<double, double, double> twoParamsWithTypes = (double x, double y) =>
    {
        return x * y;
    };
    Console.WriteLine(twoParamsWithTypes(4, 2));

    Func<double, double> operations = x => x * 2;
    operations += x => x * x;

    ProcessAndDisplayNumber(operations, 2.0);
    ProcessAndDisplayNumber(operations, 7.94);
    ProcessAndDisplayNumber(operations, 1.414);
    Console.WriteLine();
}

void ProcessAndDisplayNumber(Func<double, double> action, double value)
{
    double result = action(value);
    Console.WriteLine($"Value is {value}, result of operation is {result}");
}

void ClosureWithModification()
{
    Console.WriteLine(nameof(ClosureWithModification));
    int someVal = 5;
    Func<int, int> f = x => x + someVal;

    someVal = 7;

    Console.WriteLine(f(3));
    Console.WriteLine();
}

void ClosureWithForEach()
{
    Console.WriteLine(nameof(ClosureWithForEach));
    var values = new List<int>() { 10, 20, 30 };
    var funcs = new List<Func<int>>();
    foreach (var val in values)
    {
        funcs.Add(() => val);
    }
    foreach (var f in funcs)
    {
        Console.WriteLine(f());
    }
    Console.WriteLine();
}

参数

Lambda表达式有几种参数的方式。如果只有一个参数,只写出参数名就够。因为委托定义一个string参数,所有s的类型就是string。实现代码调用String.Format()方法来返回一个字符串,在调用该委托时,就把字符串写到控制台上:

Func<string,string>oneParam=s=>String.Format{
    "change uppercase{0}",s.ToUpper());
    Console.WriteLine(oneParam("test"));
}

如果委托使用多个参数,就把参数名放在花括号中,这里参数x和参数Y的类型是double,由Func<double,double,double>委托定义:

Func<double,double,double>twoParams=(x,y)=>x*y;

Console.WriteLine(twoParasWithTypes(4,2));

方便起见,可以在花括号中给变量名添加参数类型:

Func<double,double,double>twoParamsWithTypes=
(double x,double y)=>x*y;
Console.WriteLine(twoParasWithTypes(4,2));

多行代码

如果Lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐式的return语句。

Func<double,double>square=x=>x*x;

添加花括号、return语句和分好是完全合法的,通常这比不添加这些符号更容易阅读:

Func<double,double>square=x=>
{
    return x*x;
}

但是,如果在Lambda表达式的实现代码中需要多条语句,就必须添加花括号和return语句:

Func<string,string>lamdad=param=>
{
    param+=mid;
    param+="and this was added to the string.";
    return param;
};

Lambda表达式外部的变量

通过Lambda表达式可以访问Lambda表达式块外部的变量。下面的示例中,Fun<int,int>类型的Lambda表达式需要一个int参数,返回一个int。该Lambda表达式的参数用变量x定义。实现代码还访问Lambda表达式外部的变量someVal。只要不认为在调用f时,Lambda表达式创建一个以后使用的新方法。

int someVal=5;
Func<int,int>f=x=>x+someVal;

匿名类包含一个匿名方法,其实现代码、参数和返回类型由Lambda表达式定义:

public class AnonymousClass
{
    private int someVal;

    public AnonymousClass(int someVal)
    {
        this.someVal=someVal;
    }

    public int AnonymousClass(int x)
    {
        return x+someVal;
    }
}

使用Lambda表达式并调用该方法,会创建匿名类的一个实例,并传递调用该方法时变量的值。
Lambda表达式可以用于类型时一个委托的任意地方,类型是Expression或Expression时,也可以使用Lambda表达式。


http://www.kler.cn/a/510377.html

相关文章:

  • 华为AI培训-NLP实验
  • 【脑机接口数据处理】 如何读取Trode 的.rec文件 原始数据?
  • RC2在线加密工具
  • LabVIEW串口通信调试与数据接收问题
  • 017:推理框架为什么可以加速AI推理?
  • mac 安装 node
  • STL--list(双向链表)
  • Mousetrap:打造高效键盘快捷键体验的JavaScript库
  • PageHelper快速使用
  • 令牌主动失效机制实现——Redis登录优化
  • 基于 WEB 开发的房屋中介租赁销售系统设计与实现
  • Unity中实现伤害跳字效果(简单好抄)
  • springboot基于微信小程序的智慧乡村政务服务系统
  • 大数据治理:提升数据质量与合规性,助力企业数字化转型
  • 【Linux系统编程】—— 深入理解Linux进程优先级与调度机制
  • Python数据分析案例70——基于神经网络的时间序列预测(滞后性的效果,预测中存在的问题)
  • 3D 视觉语言推理中的态势感知
  • “提升大语言模型推理与规划能力的策略:思维链提示与由少至多提示”
  • 数据库基础练习1(创建表,设置外键,检查,不为空,主键等约束)安装mysql详细步骤
  • ROS通信机制全解析
  • 免签支付工具分享
  • Redis延迟队列详解
  • Mysql InnoDB B+Tree是什么?
  • Spring Boot 3.4.x 和 Micrometer 2.0 的结合 案例 以及使用方法
  • Git下载安装
  • C# 中的 HashSet<T>