C# 委托、lambda表达式和事件 (7) 持续更新

引用方法

在C++,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。

C# 委托 定义了返回类型和参数的类型。委托类包含对方法的引用,还可以包含多个方法引用。

定义委托

 public delegate double TwoLongsOp(long first, long second);

 public delegate string GetAString();

委托派生自 System.MulticastDelegate,而 System.MulticastDelegate 又派生自 System.Delegate。

public delegate string GetAString();

static void Main(string[] args)
{
    int x = 10;
    Console.WriteLine(x.ToString());

    GetAString stringFun = new GetAString(x.ToString);
    Console.WriteLine(stringFun());
}

// 以下两种方法一样
stringFun();
stringFun.Invoke();
 GetAString stringFun = new GetAString(x.ToString);
 GetAString stringFun2 = x.ToString;

委托它们类型是安全的,可以确保被调用的方法的签名是正确的。但它们不关心什么类型的对象上调用该方法,甚至不考虑该方法是静态方法,还是实例方法。

class MyClass
{
    public static string getStr()
    {
        return "Hello";
    }
}

static void Main(string[] args)
{
    GetAString stringFun = MyClass.getStr;
    Console.WriteLine(stringFun());
}

委托数组

 GetAString[] stringFun = { MyClass.getStr };
 Console.WriteLine(stringFun[0]());

泛型 Action<T> 委托表示引用一个 void 返回类型的方法。Action 可以调用 0 ~ 16 个参数的方法。

Func<T> 引用 带 返回类型的方法,Func可以调用 0 ~ 16 个参数的方法。

class MyClass
{
    public static string getString(string s)
    {
        return "Hello "+ s;
    }

    public static void Call()
    {
        Console.WriteLine("Hello Call");
    }

}

static void Main(string[] args)
{
    Func<string, string> stringFun = MyClass.getString;
    Console.WriteLine(stringFun("Wo"));
    Action fun2 = MyClass.Call;
    fun2();
}

多播委托

存储两个方法的引用

增加 +=   删除 -=

class MyClass
{
    public static void Hello(string s)
    {
        Console.WriteLine("Hello " + s);
    }

    public static void Call(string s)
    {
        Console.WriteLine("Call " + s);
    }

}

static void Main(string[] args)
{
    Action<string> action = MyClass.Hello;
    action += MyClass.Call;

    action("Zhao");

    action -= MyClass.Call;

    action("Zhao2");
}

如果 Hello 方法报错了,第二个 Call 就不会执行了。可以用以下代替。

Action<string> action = MyClass.Hello;
action += MyClass.Call;

Delegate[] delegates = action.GetInvocationList();
foreach (Action<string> action2 in delegates)
{
    try
    {
        action2("Python");
    }
    catch (Exception)
    {
    }
}

匿名方法

Action<string> action = delegate(string str)
{
    Console.WriteLine("Anonymous " + str);
};

Delegate[] delegates = action.GetInvocationList();
foreach (Action<string> action2 in delegates)
{
    try
    {
        action2("Python");
    }
    catch (Exception)
    {
    }
}

匿名方法不能使用跳转语句(break、goto 或 continue)跳到该匿名方法的外部。匿名方法内部能访问不安全的代码。也不能使用 ref 和 out 参数。但可以使用匿名方法外部定义的其他变量。

lmadba

Action<string> action = str => Console.WriteLine("lambda " + str);
Action<string> action2 = (str) => { Console.WriteLine("lambda " + str); };

匿名方法

int sum = 12;
Func<int, int> fun = x => x + sum;
Console.WriteLine(fun(12) + "  " + sum);
时间: 2024-10-12 01:36:47

C# 委托、lambda表达式和事件 (7) 持续更新的相关文章

委托、Lambda表达式、事件系列07,使用EventHandler委托

谈到事件注册,EventHandler是最常用的. EventHandler是一个委托,接收2个形参.sender是指事件的发起者,e代表事件参数. □ 使用EventHandler实现猜拳游戏 使用EventHandler实现一个猜拳游戏,每次出拳,出剪刀.石头.布这三者的其中一种. 首先抽象出一个被观察者,其中提供了事件,提供了执行事件的方法. public class FistGame { public string FistName { get; set; } public event

委托、Lambda表达式、事件系列05,Action委托与闭包

来看使用Action委托的一个实例: static void Main(string[] args) { int i = 0; Action a = () => i++; a(); a(); Console.WriteLine(i); } 结果是期望能的2.但令人好奇的是:栈上的变量i是如何传递给Action委托的? 反编译进行查看,首先看Main方法对应的IL代码: 再看c_DisplayClass1的IL代码: 从中可以看出:→在托管堆上创建了一个名为c_DisplayClass1的实例→把

委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托

在"委托.Lambda表达式.事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性"中,反编译委托,发现委托都是多播委托. 既然委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链, 它是怎样形成的?来看下面的例子: namespace ConsoleApplication3 { internal delegate void MySayDel(string msg); class Program { stati

委托、Lambda表达式、事件系列06,使用Action实现观察者模式

在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式.委托与事件的方式实现过观察者模式.本篇体验使用Action实现此模式. 就举一个足球场上的例子,当裁判吹响终场哨,胜队庆祝,失败队落寞.把裁判看作是被观察者,比赛中的两队看作是观察者. 裁判作为被观察者需要提供一个Action委托供观察者方法注册. public class Referee { public Action DoSth; public void ISayGameOver() { Co

委托、Lambda表达式、事件系列03,从委托到Lamda表达式

在"委托.Lambda表达式.事件系列02,什么时候该用委托"一文中,使用委托让代码简洁了不少. namespace ConsoleApplication2 { internal delegate bool MyCalculateDelegate(int val); class Program { static void Main(string[] args) { IEnumerable<int> source = new List<int>(){2, 3, 4

委托、Lambda表达式、事件系列02,什么时候该用委托

假设要找出整型集合中小于5的数. static void Main(string[] args) { IEnumerable<int> source = new List<int>(){2, 3, 4, 5, 6, 7, 8, 9,10, 11}; var result = GetNumbersLessThanFive(source); foreach (int n in result) { Console.WriteLine(n); } } static IEnumerable&

个人总结:匿名委托+内置委托+Lambda表达式

匿名委托+内置委托+Lambda表达式 概要 在实际开发中,项目开发框架不同,用到的技术是不一样的,这里总结一下用Linq开发,ORM之EF开发会大量使用的Lambda表达式; 正文 之前提过.Net有一套扩展在IEumberable<T>泛型接口的扩展方法,本文是从这个基础继续总结; 1.void Action<in T>: 先拿一个ForEach()来讲: public void ForEach(Action<T> action); 这个Action<T>

委托、Lambda表达式和事件

1.1 引用方法      委托是寻址方法的 .NET 版本.委托是类型安全的类.它定义了返回类型和参数的类型.委托类不仅包含对方法的引用,也可以包含对多个方法的引用. Lambda 表达式与委托直接相关.当参数是委托类型时,就可以使用Lambda表达式实现委托引用的方法. 1.2委托      当要把 方法 传送给其他方法时,需要使用 委托.以下两个示例: 启动线程和任务--在C# 中,可以告诉计算机并行运行某些新的执行序列同时运行当前的任务.这种序列就是称为线程,在其中一个基类 System

C# 委托、Lambda表达式和事件——学习总结

1.概括 1.1.委托是寻址方法的.NET版本,类似C++中的指针.委托可以理解成指向函数的指针,它是类型安全的,定义了具体的参数和返回值. ——定义一个委托,实际上是定义一个类.委托是对方法的引用,如方法Func,把其功能交给委托的类来实现. ——委托的作用:结合泛型,可以实现功能上的扩展(如针对整型的函数,可以通过委托指向多种函数,实现类中某个属性的比较).Lambda表达式需要使用委托定义.事件需要使用到委托. 1.2.Lambda表达式与委托直接相关.Lambda表达式可以理解成一个简单

委托、匿名函数、Lambda表达式和事件的学习

委托: 还记得C++里的函数指针么?大家可以点击这里查看一下以前的笔记.C#的委托和C++中的函数指针效果一致. 当我们需要将函数作为对象进行传递和使用时就需要用到委托. 下面我们看一个例子: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Test 8 { 9 cl