首页 > 编程语言 >C# Delegate 委托:是一种类型安全的委托类型,用于引用方法

C# Delegate 委托:是一种类型安全的委托类型,用于引用方法

时间:2024-09-09 10:51:51浏览次数:8  
标签:string 委托 C# void static Delegate 方法 public

在C#中,delegate 是一种类型安全的委托类型,它用于引用方法。可以将方法作为参数传递给其他方法,或者动态选择在运行时调用哪个方法。delegate 可以看作是对方法的引用类型,它提供了一种将方法视作对象来处理的机制。

1. 基本概念:什么是委托 (delegate)?

委托类似于函数指针的概念,但与C/C++中的函数指针不同,C#中的委托是类型安全的,并且只能引用与其签名匹配的方法(即返回类型和参数类型一致)。

示例:定义和使用委托

// 定义一个委托类型,它可以引用返回类型为 void,参数为 string 的方法
public delegate void PrintMessage(string message);

class Program
{
    // 定义一个与委托匹配的方法
    public static void PrintToConsole(string message)
    {
        Console.WriteLine(message);
    }

    static void Main(string[] args)
    {
        // 创建一个委托实例,指向 PrintToConsole 方法
        PrintMessage printer = PrintToConsole;

        // 调用委托,它会调用 PrintToConsole 方法
        printer("Hello, Delegate!");  // 输出:Hello, Delegate!
    }
}

在这个示例中:

  • delegate void PrintMessage(string message); 定义了一个委托类型 PrintMessage,它可以引用任何返回 void 且接受 string 参数的方法。
  • Main 方法中,printer 是一个委托实例,指向 PrintToConsole 方法。通过 printer("Hello, Delegate!"),委托调用了 PrintToConsole 方法。

2. 委托的签名

委托的签名决定了它可以引用什么样的方法。只有当方法的返回类型和参数类型与委托的签名匹配时,才能被该委托引用。

示例:不同的委托签名

// 定义不同的委托类型
public delegate int Calculate(int a, int b);          // 返回 int,接受两个 int 参数
public delegate string GetMessage();               // 返回 string,没有参数
public delegate void ProcessData(int data);     // 返回 void,接受一个 int 参数

class Program
{
    // 与 Calculate 委托匹配的方法
    public static int Add(int x, int y) => x + y;
    public static int Multiply(int x, int y) => x * y;

    // 与 GetMessage 委托匹配的方法
    public static string WelcomeMessage() => "Welcome!";
    
    // 与 ProcessData 委托匹配的方法
    public static void DisplayData(int data) => Console.WriteLine($"Data: {data}");

    static void Main(string[] args)
    {
        // 使用不同的委托
        Calculate calc = Add;
        Console.WriteLine(calc(3, 4));  // 输出:7

        calc = Multiply;
        Console.WriteLine(calc(3, 4));  // 输出:12

        GetMessage msg = WelcomeMessage;
        Console.WriteLine(msg());  // 输出:Welcome!

        ProcessData processData = DisplayData;
        processData(100);  // 输出:Data: 100
    }
}

3. 多播委托

委托还可以同时引用多个方法,这称为多播委托。当多播委托被调用时,它会依次调用每个方法。如果委托有返回值,只有最后一个方法的返回值会被保留。

示例:多播委托

public delegate void Notify();

class Program
{
    public static void NotifyByEmail()
    {
        Console.WriteLine("Notified by Email");
    }

    public static void NotifyBySMS()
    {
        Console.WriteLine("Notified by SMS");
    }

    static void Main(string[] args)
    {
        // 创建多播委托
        Notify notify = NotifyByEmail;
        notify += NotifyBySMS;

        // 调用多播委托
        notify();  // 输出:
                   // Notified by Email
                   // Notified by SMS
    }
}
在这个例子中,notify 委托依次调用了 NotifyByEmailNotifyBySMS 方法。

4. 委托作为参数

可以将委托作为参数传递给其他方法,这样可以实现更灵活的代码设计。

示例:委托作为参数

public delegate void ActionDelegate(string message);

class Program
{
    // 定义一个方法,接受一个委托作为参数
    public static void ExecuteAction(ActionDelegate action, string message)
    {
        action(message);  // 调用传入的委托
    }

    public static void PrintToUpper(string message)
    {
        Console.WriteLine(message.ToUpper());
    }

    static void Main(string[] args)
    {
        ActionDelegate action = PrintToUpper;
        ExecuteAction(action, "Hello, Delegate!");  // 输出:HELLO, DELEGATE!
    }
}

在这个示例中,ExecuteAction 方法接受一个委托作为参数,它通过委托调用传入的方法。

5. 匿名方法和 Lambda 表达式

C# 支持使用匿名方法或 Lambda 表达式创建委托,而不需要显式定义方法。这使得代码更简洁,尤其在只需使用一次的方法时。

5.1 匿名方法

public delegate void Display(string message);

class Program
{
    static void Main(string[] args)
    {
        // 使用匿名方法创建委托
        Display display = delegate(string msg)
        {
            Console.WriteLine(msg);
        };

        display("Hello, Anonymous Method!");  // 输出:Hello, Anonymous Method!
    }
}

5.2 Lambda 表达式

Lambda 表达式是匿名方法的简洁语法,通常用于委托和事件处理。

public delegate void Display(string message);

class Program
{
    static void Main(string[] args)
    {
        // 使用 Lambda 表达式创建委托
        Display display = (msg) => Console.WriteLine(msg);

        display("Hello, Lambda!");  // 输出:Hello, Lambda!
    }
}

6. 内置委托类型:ActionFunc

C# 提供了内置的委托类型 ActionFunc,用于简化常见的委托场景:

  • Action:表示一个返回 void 的委托,可以有 0 到 16 个输入参数。
  • Func:表示一个有返回值的委托,可以有 0 到 16 个输入参数,最后一个泛型参数为返回类型。
示例:使用 ActionFunc

class Program
{
    static void Main(string[] args)
    {
        // 使用 Action
        Action<string> print = (msg) => Console.WriteLine(msg);
        print("Hello, Action!");  // 输出:Hello, Action!

        // 使用 Func
        Func<int, int, int> add = (x, y) => x + y;
        Console.WriteLine(add(3, 4));  // 输出:7
    }
}

总结

  • 委托 (delegate) 是 C# 中用于引用方法的类型,可以动态选择和调用方法。
  • 多播委托 允许一个委托同时引用多个方法。
  • 匿名方法和 Lambda 表达式 是创建委托的简洁方式。
  • 内置的 ActionFunc 委托类型简化了常见的委托定义。

标签:string,委托,C#,void,static,Delegate,方法,public
From: https://blog.csdn.net/liang077877/article/details/142052700

相关文章

  • C++里面的iostream是什么东西?
    小弟不才,看了百度的介绍更乱了。。我刚接触c++,我感觉很有意思,今天看c++primer里面介绍过iostream。但是怎么看都不懂。代码里面也出现了#include<iostream>。我想请教一下,iostream是个库,可不可以理解成是一个仓库,里面装的都是C的代码?另外,IO是不是iostream的缩写? C++编译系统提......
  • 【优技教育】Oracle 19c OCP 082题库(第16题)- 2024年修正版
    【优技教育】Oracle19cOCP082题库(Q16题)-2024年修正版考试科目:1Z0-082考试题量:90通过分数:60%考试时间:150min本文为(CUUG原创)整理并解析,转发请注明出处,禁止抄袭及未经注明出处的转载。原文地址:http://www.cuug.com/index.php?s=/home/article/detail/id/3397.html第......
  • C++学习笔记(曾经我看不懂的代码2:基于范围的for循环、auto使用、stl容器、template模
    不知不觉c++程序设计:标准库已经看了一大半了,学到了很多,很多曾经在网上和在书上看到却看不懂的代码,在看完标准库中的大半内容以后,都能大致的理清代码的含义。代码模板一:for(auto&a:arr)1、基于范围的for循环:a为迭代变量,arr为迭代范围,&表示引用。写一个例子:#include<ios......
  • Canvas绘制图片合成样式
    效果图web*{margin:0;padding:0;}.container{position:relative;width:328px;height:328px;margin:100pxauto;}.containerimg{position:absolute;width:328px;height:328px;}#canvas{posi......
  • 免费OCR 文字识别工具
    免费:本项目所有代码开源,完全免费。方便:解压即用,离线运行,无需网络。高效:自带高效率的离线OCR引擎,内置多种语言识别库。灵活:支持命令行、HTTP接口等外部调用方式。功能:截图OCR/批量OCR/PDF识别/二维码/公式识别下载地址:https://pan.quark.cn/s/f263ecc221b7......
  • ACPI随笔
    ACPI(AdvancedConfigurationandPowerInterface)基本概念RSDP:是ACPI数据结构中的第一个表,用于引导ACPI表的查找过程。根系统描述指针,指向RSDT或XSDT的位置。RSDT和XSDT:根表和扩展表,提供其他ACPI表的位置。FADT:固定配置表,包含ACPI固件的配置信息。AC......
  • C++ iostream、iomanip 头文件详解
    C++iostream、iomanip头文件详解首先,我们来看看iostream。相信大家都知道iostream,这个库可以说是最常用的几个库之一了。iostream库提供了输入输出流。比如cin、cout,都是在iostream里的。所以,我们经常会用到iostream这个库。iostream这个名字很好理解,InputOutputStream,输......
  • C/C++中extern函数使用详解
    extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定目录一、定义和声明的区别二、extern用法2.1extern函数2.2extern变量2.3在C++文件中调用C方式编译的函数三、通俗讲......
  • Docker镜像使用
    一、查看设置docker镜像仓库地址cat/etc/docker/daemon.json修改完成后,需要重启docker才会生效,systemctlrestartdockerdockerinfo在最后就能看到镜像仓库地址列表在通过dockerpull域名/library/镜像名称:版本号可以拉取镜像到本地dockerimages查看本地镜像列表......
  • [LeetCode] 2181. Merge Nodes in Between Zeros
    Youaregiventheheadofalinkedlist,whichcontainsaseriesofintegersseparatedby0's.ThebeginningandendofthelinkedlistwillhaveNode.val==0.Foreverytwoconsecutive0's,mergeallthenodeslyinginbetweenthemintoasing......