首页 > 编程语言 >#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-委托、匿名方法、Lambda、泛型委托、表达式树的进化史

#yyds干货盘点#【愚公系列】2023年02月 .NET/C#知识点-委托、匿名方法、Lambda、泛型委托、表达式树的进化史

时间:2023-02-27 12:04:06浏览次数:37  
标签:知识点 Console 委托 yyds int MyDelegate WriteLine 方法

前言

在 .NET 中,委托是一种类型,它可以持有对一个或多个方法的引用,并允许将这些方法作为参数传递给其他方法。.NET 中的委托类似于 C 和 C++ 中的函数指针,但具有更高的类型安全性和其他功能。

委托的概念最早可以追溯到早期的编程语言,例如Simula和Smalltalk。然而,C# 的委托实现受到了函数指针和C++中的函数对象的启发。

在.NET框架中,委托最初被引入为事件处理程序的机制。事件是一种广泛使用的编程模型,用于在程序中处理异步和交互性操作。事件可以被认为是类似于信号和槽机制的一种形式。

委托在.NET中被广泛使用,不仅用于事件处理程序,还用于Lambda表达式和LINQ查询等高级编程概念。它们使得在.NET框架中编写高效和易于理解的代码变得更加容易。

一、委托、匿名方法、Lambda、泛型委托、表达式树的进化史

1.委托

1.1 无返回值委托

// 创建委托实例
CallbackFunction callback = new CallbackFunction(CallbackMethod);
// 调用方法并传入委托作为回调参数
ProcessData(callback);

Console.ReadKey();


// 接收委托作为回调参数的方法
static void ProcessData(CallbackFunction callback)
{
    for (int i = 1; i <= 10; i++)
    {
        // 调用委托,传入当前的循环计数器值
        callback(i);
    }
}

// 委托所指向的方法,用于在每次循环中输出计数器的值
static void CallbackMethod(int value)
{
    Console.WriteLine("Callback called with value: " + value);
}

delegate void CallbackFunction(int value);

在这里插入图片描述

在上面的示例中,我们首先定义了一个委托类型 CallbackFunction,它接收一个 int 类型的参数并不返回任何值。接下来,我们创建了一个 CallbackFunction 类型的委托实例 callback,并将一个方法 CallbackMethod 作为参数传递给它。

接着,我们调用了 ProcessData 方法,并将 callback 委托作为回调参数传递给它。在 ProcessData 方法中,我们使用一个 for 循环来遍历整数 1 到 10,并在每次循环中调用 callback 委托,将当前的计数器值作为参数传递给它。

最后,我们定义了 CallbackMethod 方法,它将在每次委托被调用时被执行。在本例中,它只是简单地将传入的参数打印到控制台上。

总之,这个例子演示了如何使用 .NET 委托来实现简单的回调功能。

1.2 有返回值委托

using System;

MyDelegate add = AddNumbers;
MyDelegate subtract = SubtractNumbers;

int result1 = add(5, 3);
Console.WriteLine("5 + 3 = " + result1);

int result2 = subtract(5, 3);
Console.WriteLine("5 - 3 = " + result2);


static int AddNumbers(int x, int y)
{
    return x + y;
}

static int SubtractNumbers(int x, int y)
{
    return x - y;
}

delegate int MyDelegate(int x, int y);

在这里插入图片描述 在此示例中,我们定义了一个委托类型 MyDelegate,它接受两个 int 类型的参数并返回一个 int 类型的值。然后,我们创建了两个委托实例,分别指向两个不同的方法 AddNumbers 和 SubtractNumbers。这些方法分别接受两个参数并返回它们的和或差。

在 Main 方法中,我们调用了这些委托实例,并将它们作为函数来使用,传递了两个整数参数,并将结果存储在变量 result1 和 result2 中,然后将这些结果输出到控制台。

1.3 多播委托

public delegate void MulticastDelegateExample(int value); 

public class MulticastDelegateExampleClass
{
    public static void PrintNumber(int value)
    {
        Console.WriteLine("PrintNumber(): {0}", value);
    }

    public static void PrintMoney(int value)
    {
        Console.WriteLine("PrintMoney(): {0}", value);
    }

    public static void PrintHexadecimal(int value)
    {
        Console.WriteLine("PrintHexadecimal(): {0:X}", value);
    }

    public static void Main()
    {
        // Create a multicast delegate.
        MulticastDelegateExample mde = new MulticastDelegateExample(PrintNumber);

        // Add PrintMoney and PrintHexadecimal to invocation list.
        mde += PrintMoney;
        mde += PrintHexadecimal;

        // Invoke the multicast delegate.
        mde(123);

        // Remove PrintHexadecimal from the invocation list.
        mde -= PrintHexadecimal;

        Console.WriteLine("-----");

        // Invoke the multicast delegate again.
        mde(123);
    }
}

在这里插入图片描述

2.匿名方法

PrintDelegate printDelegate = delegate (string message)
{
    Console.WriteLine("Anonymous method: " + message);
};

printDelegate("Hello, world!");
delegate void PrintDelegate(string message);

在这里插入图片描述 这个程序定义了一个委托类型 PrintDelegate,它接受一个字符串参数并返回 void。然后,在 Main 方法中,我们使用匿名方法创建一个 PrintDelegate 实例,并将其赋值给变量 printDelegate。匿名方法的代码块包含一个输出语句,它将字符串 "Anonymous method: " 和传入的消息连接起来输出到控制台。最后,我们调用 printDelegate,将字符串 "Hello, world!" 作为参数传递给它,匿名方法就会执行并输出 "Anonymous method: Hello, world!" 到控制台。

需要注意的是,在上面的代码中,匿名方法是使用 delegate 关键字创建的。匿名方法的语法与普通方法非常相似,不同之处在于它没有名称,而是直接作为委托类型的实例赋值给一个变量。

3.Lambda表达式

// 使用Lambda表达式定义一个方法并将其分配给委托
Calculate add = (x, y) => x + y;

// 使用Lambda表达式定义另一个方法并将其分配给委托
Calculate subtract = (x, y) => x - y;

// 调用委托以执行Lambda表达式所定义的方法
int result1 = add(5, 3);
int result2 = subtract(5, 3);

Console.WriteLine($"5 + 3 = {result1}");
Console.WriteLine($"5 - 3 = {result2}");

delegate int Calculate(int x, int y);

在这里插入图片描述 在上面的示例中,我们定义了一个名为Calculate的委托,它接受两个int类型的参数并返回一个int类型的结果。然后,我们使用Lambda表达式定义了两个方法(一个加法和一个减法),并将它们分配给委托add和subtract。

4.泛型委托

1、基本使用

using System;

// 创建一个 MyDelegate<int> 委托实例
MyDelegate<int> myIntDelegate = new MyDelegate<int>(Add);

int result = myIntDelegate(2, 3);
Console.WriteLine("2 + 3 = {0}", result);

// 创建一个 MyDelegate<string> 委托实例
MyDelegate<string> myStringDelegate = new MyDelegate<string>(Concatenate);

string str = myStringDelegate("Hello, ", "World!");
Console.WriteLine(str);


static int Add(int a, int b)
{
    return a + b;
}

static string Concatenate(string a, string b)
{
    return a + b;
}

// 定义一个泛型委托
delegate T MyDelegate<T>(T a, T b);

在这里插入图片描述

在这个示例中,我们首先定义了一个泛型委托 MyDelegate<T>,它接受两个类型为 T 的参数,并返回类型为 T 的值。然后,我们创建了两个委托实例,一个用于整数加法,另一个用于字符串连接。最后,我们分别调用这两个委托实例,并打印结果。

这个示例展示了泛型委托在.NET中的用法,它可以接受任何类型的参数和返回值,使得我们可以写出更加灵活的代码。

2、Action和Func

//Action无返回值、Func有返回值
//方法一:
Func<int, int, int> cAdd1 = (int x, int y) => { return x + y; };
int result1 = cAdd1(5, 6);
//方法二:
Func<int, int, int> cAdd2 = (x, y) => { return x + y; };
int result2 = cAdd2(5, 6);
//方法三:
Func<int, int, int> cAdd3 = (x, y) => x + y;
int result3 = cAdd2(5, 6);

Console.WriteLine(result3);

在这里插入图片描述

5.表达式树

1、编译使用

using System.Linq.Expressions;

Expression<Func<int, int, int>> exp = (x, y) => x + y;
Func<int, int, int> fun = exp.Compile();
int result = fun(2, 3);

Console.WriteLine(result);

在这里插入图片描述 2、拼接使用

// 定义参数
using System.Linq.Expressions;

ParameterExpression x = Expression.Parameter(typeof(int), "x");
ParameterExpression y = Expression.Parameter(typeof(int), "y");

// 创建表达式目录树
BinaryExpression sum = Expression.Add(x, y);

// 创建委托
Func<int, int, int> sumFunc = Expression.Lambda<Func<int, int, int>>(sum, x, y).Compile();

// 使用委托计算结果
int result = sumFunc(1, 2);
Console.WriteLine(result);

在这里插入图片描述

在这个例子中,我们首先定义了两个参数 x 和 y,它们分别表示要相加的两个整数。然后,我们创建了一个 BinaryExpression 对象,它表示将 x 和 y 相加的操作。接着,我们使用 Expression.Lambda 方法将表达式目录树转换为一个委托,并编译它以生成可执行代码。最后,我们使用生成的委托计算 1 + 2 的结果并输出它。

请注意,表达式目录树的主要优点之一是它们是类型安全的。在上面的示例中,我们明确指定了参数和返回值的类型,因此编译器可以在编译时执行类型检查,从而避免在运行时出现类型错误。

标签:知识点,Console,委托,yyds,int,MyDelegate,WriteLine,方法
From: https://blog.51cto.com/u_15437432/6087033

相关文章

  • 免费领取2023年上半年系统集成项目管理工程师重要知识点10G学习资料包
    课课家软考学院为2023年上半年系统集成项目管理工程师考生整理了2023年上半年系统集成项目管理工程师重要知识点10G学习资料的内容,希望能帮助考生掌握系统集成项目管理......
  • 委托
    委托和事件委托委托是一个类型安全的函数指针,表示对具有特定参数列表和返回类型的方法的引用(引用类型)使用场景:用于将方法作为参数传递给其他方法,是对方法的多态例如......
  • [Unity/C#]委托+协程,依次启动多播委托里协程的方法
    1//委托的定义2publicdelegateIEnumeratorActiveDuringTurn(Player[]otherplayers);34publiceventActiveDuringTurnUEvent;567//依次启动协程......
  • WPF知识点备忘录——控件模板
    模板<Application.Resources><ResourceDictionary><!--将画刷等从模板拆分出来,方便重用--><RadialGradientBrushRadiusX="1"R......
  • 免费领取2023年上半年信息系统项目管理师重要知识点10G资料包
    课课家软考学院为2023年上半年信息系统项目管理师考生整理了2023年上半年信息系统项目管理师重要知识点10G学习资料的内容,希望能帮助考生掌握信息系统项目管理师的重要......
  • Python3中zip()函数知识点总结
    1.引言在本文中,我将带领大家深入了解​​Python​​中的​​zip()​​函数,使用它可以提升大家的工作效率。闲话少说,我们直接开始吧!2.基础知识首先,我们来介绍一些基础知识......
  • 有关图片的知识点
    常见的图片格式类型SVG(ScalableVectorGraphics):矢量图形格式,可以无限放大而不失真,适合于网页图形和动画等应用。JPEG(JointPhotographicExpertsGroup):用于存储......
  • C#/.NET知识点总结【泛型】
     泛型极大提高代码可用性,可以重复使用对象,定义一个反省对象后,我们可以赋值成string类型,int类型,类型是安全的性能也有提高  https://www.ktanx.com/blog/p/665 ......
  • 297个机器学习彩图知识点(14)
    导读本系列将持续更新20个机器学习的知识点,欢迎关注。1.独立同分布2.KNN填补缺失值3.填补缺失值4.拐点5.参数初始化6.初始权重7.工具变量8.交叉......
  • #yyds干货盘点# LeetCode面试题:移除元素
    1.简述:给你一个数组nums 和一个值val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地......