设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间02 现在时间02 缓存数据 现已加入洗脑好歌曲豪华午餐

现已加入洗脑好歌曲豪华午餐 -- Outside

查看: 659|回复: 1

.NET Core 委托原理解析(最新推荐)

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
35
主题
27
精华
0
金钱
100
积分
64
注册时间
2023-9-30
最后登录
2025-6-1

发表于 2025-2-16 12:58:30 | 显示全部楼层 |阅读模式
目录
  • 1. 委托的基本概念
    • 1.1 定义委托
    • 1.2 实例化委托
    • 1.3 调用委托
  • 2.委托的类型
    • 1. 单播委托(Singlecast Delegate)
    • 2. 多播委托(Multicast Delegate)
    • 3. 泛型委托(Generic Delegate)
    • 3.1 简单的泛型委托
    • 3.2 多参数泛型委托
    • 4. 内置委托类型
    • 4.1 Action 委托
    • 4.2 Func 委托
    • 4.3 Predicate 委托
    • 5. 匿名方法委托
    • 6. Lambda 表达式委托
    • 7. 事件委托
    • 8. 异步委托
    • 9. 动态委托
  • 3. 委托的运行原理
    • 3.1 委托的内部结构
    • 3.2 委托的调用
    • 3.3 委托的优化
  • 4. 委托的应用场景
    • 4.1 事件处理
    • 4.2 回调机制
    • 4.3 异步编程
  • 5. 总结

    在 .NET Core 中,委托(Delegate)是一种类型安全的函数指针,它允许你将方法作为参数传递给其他方法,或者将方法存储在变量中以便稍后调用。委托在事件处理、回调机制以及异步编程中非常有用。理解委托的运行原理对于掌握 .NET Core 的高级编程技巧至关重要。

    1. 委托的基本概念

    委托是一种引用类型,它引用一个或多个方法。委托定义了方法的签名(参数类型和返回类型),因此只有具有相同签名的方法才能被委托引用。

    1.1 定义委托

    你可以通过 

    1. delegate
    复制代码
     关键字来定义一个委托类型。例如:

    1. // 定义一个委托类型
    2. public delegate void GreetDelegate(string name);
    复制代码

    这个委托类型 

    1. GreetDelegate
    复制代码
     可以引用任何具有 
    1. void
    复制代码
     返回类型和 
    1. string
    复制代码
     参数的方法。

    1.2 实例化委托

    一旦定义了委托类型,你可以创建该委托的实例,并将方法赋值给它。例如:

    1. // 与委托签名匹配的方法
    2. public void Greet(string name)
    3. {
    4. Console.WriteLine($"Hello, {name}!");
    5. }
    6. // 创建委托实例并绑定方法
    7. GreetDelegate del = new GreetDelegate(Greet);
    复制代码

    在这个例子中,

    1. del
    复制代码
     是一个委托实例,它引用了 
    1. Greet
    复制代码
     方法。

    1.3 调用委托

    你可以像调用方法一样调用委托:

    1. // 调用委托
    2. del("World");
    复制代码

    这会调用 

    1. del
    复制代码
     方法,并输出 
    1. "Hello, World!"
    复制代码

    2.委托的类型

    1. 单播委托(Singlecast Delegate)

    单播委托是指一个委托实例只能引用一个方法。这是最基本的委托类型。

    1. public delegate void GreetDelegate(string message);
    2. public void ShowMessage(string message)
    3. {
    4. Console.WriteLine(message);
    5. }
    6. GreetDelegate del = new GreetDelegate(ShowMessage);
    7. del("Hello, World!"); // 输出:Hello, World!
    复制代码

    2. 多播委托(Multicast Delegate)

    多播委托是指一个委托实例可以引用多个方法。通过 

    1. +=
    复制代码
     运算符可以将多个方法添加到委托实例中,并通过 
    1. -=
    复制代码
     运算符移除方法。

    1. public void ShowMessage1(string message)
    2. {
    3. Console.WriteLine($"Message 1: {message}");
    4. }
    5. public void ShowMessage2(string message)
    6. {
    7. Console.WriteLine($"Message 2: {message}");
    8. }
    9. public void ShowMessage3(string message)
    10. {
    11. Console.WriteLine($"Message 3: {message}");
    12. }
    13. GreetMulticastDelegate del = new GreetMulticastDelegate(ShowMessage1);
    14. del += ShowMessage2;
    15. del += ShowMessage3;
    16. del -= ShowMessage2;
    17. del("Hello, World!");
    复制代码

    在这个例子中,

    1. del
    复制代码
     委托实例引用了多个方法:将
    1. ShowMessage1,ShowMessage2
    复制代码
     和 
    1. ShowMessage3
    复制代码
    添加到了多播委托实例中,然后并通过 
    1. -=
    复制代码
     运算符移除
    1. ShowMessage2
    复制代码
    。然后调用 
    1. del("Hello, World!")
    复制代码
     时,三个方法都会被调用,输出如下:

    1. Message 1: Hello, World!
    2. //ShowMessage2方法已移除
    3. Message 3: Hello, World!
    复制代码

    3. 泛型委托(Generic Delegate)

    泛型委托是 C# 中的一种特殊委托类型,它允许你定义可以处理多种数据类型的委托。通过使用泛型,你可以编写更通用、更灵活的代码,而不需要为每种数据类型单独定义委托。

    以下是几个泛型委托的示例,展示了如何使用泛型委托处理不同类型的数据。

    3.1 简单的泛型委托

    1. public delegate T MyGenericDelegate<T>(T arg);
    2. public int Square(int x)
    3. {
    4. return x * x;
    5. }
    6. public string Reverse(string s)
    7. {
    8. return new string(s.Reverse().ToArray());
    9. }
    10. MyGenericDelegate<int> intDelegate = new MyGenericDelegate<int>(Square);
    11. Console.WriteLine(intDelegate(5)); // 输出:25
    12. MyGenericDelegate<string> stringDelegate = new MyGenericDelegate<string>(Reverse);
    13. Console.WriteLine(stringDelegate("hello")); // 输出:olleh
    复制代码
    • • 说明
      • • 
        1. MyGenericDelegate
        复制代码
         实例化了一个处理 
        1. int
        复制代码
         类型数据的委托。
      • • 
        1. MyGenericDelegate
        复制代码
         实例化了一个处理 
        1. string
        复制代码
         类型数据的委托。

    3.2 多参数泛型委托

    1. public delegate TResult MyGenericDelegate<T1, T2, TResult>(T1 arg1, T2 arg2);
    2. public int Add(int a, int b)
    3. {
    4. return a + b;
    5. }
    6. public string Concat(string s1, string s2)
    7. {
    8. return s1 + s2;
    9. }
    10. MyGenericDelegate<int, int, int> intDelegate = new MyGenericDelegate<int, int, int>(Add);
    11. Console.WriteLine(intDelegate(3, 5)); // 输出:8
    12. MyGenericDelegate<string, string, string> stringDelegate = new MyGenericDelegate<string, string, string>(Concat);
    13. Console.WriteLine(stringDelegate("Hello, ", "World!")); // 输出:Hello, World!
    复制代码
    • • 说明
      • • 
        1. MyGenericDelegate
        复制代码
         实例化了一个处理两个 
        1. int
        复制代码
         类型参数并返回 
        1. int
        复制代码
         类型结果的委托。
      • • 
        1. MyGenericDelegate
        复制代码
         实例化了一个处理两个 
        1. string
        复制代码
         类型参数并返回 
        1. string
        复制代码
         类型结果的委托。

    4. 内置委托类型

    C# 提供了一些内置的泛型委托类型,可以直接使用,而无需自定义委托。

    4.1 
    1. Action
    复制代码
     委托

    1. Action
    复制代码
     委托用于引用没有返回值的方法。它可以有 0 到 16 个参数。

    1. Action<string> action = (message) => Console.WriteLine(message);
    2. action("Hello, World!"); // 输出:Hello, World!
    复制代码

    4.2 
    1. Func
    复制代码
     委托

    1. Func
    复制代码
     委托用于引用有返回值的方法。它可以有 0 到 16 个参数,最后一个泛型参数是返回值类型。

    1. Func<int, int, int> add = (a, b) => a + b;
    2. Console.WriteLine(add(3, 5)); // 输出:8
    复制代码

    4.3 
    1. Predicate
    复制代码
     委托

    1. Predicate
    复制代码
     委托用于引用返回布尔值的方法,通常用于条件判断。

    1. Predicate<int> isEven = (num) => num % 2 == 0;
    2. Console.WriteLine(isEven(4)); // 输出:True
    复制代码

    5. 匿名方法委托

    匿名方法允许你直接定义委托的实现,而无需显式声明一个方法。

    1. MyDelegate del = delegate(string message)
    2. {
    3. Console.WriteLine(message);
    4. };
    5. del("Hello, World!"); // 输出:Hello, World!
    复制代码

    6. Lambda 表达式委托

    Lambda 表达式是一种更简洁的匿名方法写法,通常用于定义委托。

    1. Action<string> action = (message) => Console.WriteLine(message);
    2. action("Hello, World!"); // 输出:Hello, World!
    3. Func<int, int, int> add = (a, b) => a + b;
    4. Console.WriteLine(add(3, 5)); // 输出:8
    复制代码

    7. 事件委托

    事件是一种特殊的委托,通常用于实现观察者模式。事件委托通常与 

    1. EventHandler
    复制代码
     或 
    1. EventHandler
    复制代码
     一起使用。

    1. public class Button
    2. {
    3. public event EventHandler Click;
    4. public void OnClick()
    5. {
    6. Click?.Invoke(this, EventArgs.Empty);
    7. }
    8. }
    9. public class Program
    10. {
    11. public static void Main()
    12. {
    13. Button button = new Button();
    14. button.Click += (sender, e) => Console.WriteLine("Button clicked!");
    15. button.OnClick(); // 输出:Button clicked!
    16. }
    17. }
    复制代码

    8. 异步委托

    异步委托允许你异步调用方法,通常与 

    1. BeginInvoke
    复制代码
     和 
    1. EndInvoke
    复制代码
     一起使用。

    1. public delegate int MyAsyncDelegate(int x, int y);
    2. public int Add(int a, int b)
    3. {
    4. return a + b;
    5. }
    6. MyAsyncDelegate del = new MyAsyncDelegate(Add);
    7. IAsyncResult result = del.BeginInvoke(3, 5, null, null);
    8. int sum = del.EndInvoke(result);
    9. Console.WriteLine(sum); // 输出:8
    复制代码

    9. 动态委托

    动态委托允许你在运行时动态创建和调用委托。

    1. public int Multiply(int a, int b)
    2. {
    3. return a * b;
    4. }
    5. var method = typeof(Program).GetMethod("Multiply");
    6. var del = Delegate.CreateDelegate(typeof(Func<int, int, int>), null, method);
    7. int result = (del as Func<int, int, int>)(3, 5);
    8. Console.WriteLine(result); // 输出:15
    复制代码

    3. 委托的运行原理

    委托的运行原理涉及到 .NET Core 的运行时机制和内部实现。以下是委托运行原理的关键点:

    3.1 委托的内部结构

    在 .NET Core 中,委托是一个类,它继承自 

    1. System.MulticastDelegate
    复制代码
     类。
    1. System.MulticastDelegate
    复制代码
     类又继承自 
    1. System.Delegate
    复制代码
     类。委托类包含以下关键成员:

    • • 
      1. _target
      复制代码
      :指向调用方法的对象实例(如果是静态方法,则为 
      1. null
      复制代码
      )。
    • • 
      1. _methodPtr
      复制代码
      :指向方法的函数指针。
    • • 
      1. _invocationList
      复制代码
      :用于存储多播委托中的多个方法。

    3.2 委托的调用

    当你调用委托时,.NET Core 运行时会执行以下步骤:

    • 1. 检查委托实例是否为**** 
      1. **null**
      复制代码
      :如果委托实例为 
      1. null
      复制代码
      ,则会抛出 
      1. NullReferenceException
      复制代码
    • 2. 调用委托的**** 
      1. **Invoke**
      复制代码
       ****方法:委托实例的 
      1. Invoke
      复制代码
       方法会被调用,该方法会根据 
      1. _target
      复制代码
       和 
      1. _methodPtr
      复制代码
       调用实际的方法。
    • 3. 处理多播委托:如果委托是多播委托(即 
      1. _invocationList
      复制代码
       不为 
      1. null
      复制代码
      ),则 
      1. Invoke
      复制代码
       方法会遍历 
      1. _invocationList
      复制代码
      ,依次调用每个方法。

    3.3 委托的优化

    .NET Core 对委托的调用进行了优化,以提高性能。例如,对于单播委托(即只引用一个方法的委托),.NET Core 会直接调用方法,而不需要通过 

    1. Invoke
    复制代码
     方法。

    4. 委托的应用场景

    委托在 .NET Core 中有多种应用场景,以下是一些常见的场景:

    4.1 事件处理

    委托在事件处理中非常常见。事件是一种特殊的委托,它允许对象在发生某些事情时通知其他对象。例如:

    1. C#public class Button
    2. {
    3. public event Action Click;
    4. public void OnClick()
    5. {
    6. Click?.Invoke();
    7. }
    8. }
    9. public class Program
    10. {
    11. public static void Main()
    12. {
    13. Button button = new Button();
    14. button.Click += () => Console.WriteLine("Button clicked!");
    15. button.OnClick();
    16. }
    17. }
    复制代码

    在这个例子中,

    1. Button
    复制代码
     类定义了一个 
    1. Click
    复制代码
     事件,当 
    1. OnClick
    复制代码
     方法被调用时,事件处理程序会被触发。

    4.2 回调机制

    委托可以用于实现回调机制,允许一个方法在完成时通知另一个方法。例如:

    1. public void DoWork(Action callback)
    2. {
    3. // 执行一些工作
    4. Console.WriteLine("Work is done.");
    5. // 调用回调方法
    6. callback?.Invoke();
    7. }
    8. public void Main()
    9. {
    10. DoWork(() => Console.WriteLine("Callback called."));
    11. }
    复制代码

    在这个例子中,

    1. DoWork
    复制代码
     方法在完成工作后调用传入的回调方法。

    4.3 异步编程

    委托在异步编程中也非常有用。例如,

    1. Task
    复制代码
     类的 
    1. ContinueWith
    复制代码
     方法允许你在任务完成时执行一个委托:

    1. Task.Run(() => Console.WriteLine("Task is running..."))
    2. .ContinueWith(task => Console.WriteLine("Task is completed."));
    复制代码

    5. 总结

    委托是 .NET Core 中一个非常强大的特性,它允许你将方法作为参数传递、存储和调用。理解委托的运行原理有助于你更好地利用这一特性,特别是在事件处理、回调机制和异步编程中。通过掌握委托,你可以编写更加灵活和可扩展的代码。

    到此这篇关于.NET Core 委托原理解析的文章就介绍到这了,更多相关.NET Core 委托原理内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!


    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
    晓枫资讯-科技资讯社区-免责声明
    免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
          1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
          2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
          3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
          4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
          5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
    http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

      离线 

    TA的专栏

    • 打卡等级:无名新人
    • 打卡总天数:2
    • 打卡月天数:0
    • 打卡总奖励:34
    • 最近打卡:2024-03-23 01:15:42
    等级头衔

    等級:晓枫资讯-列兵

    在线时间
    0 小时

    积分成就
    威望
    0
    贡献
    0
    主题
    0
    精华
    0
    金钱
    50
    积分
    12
    注册时间
    2023-6-3
    最后登录
    2024-3-23

    发表于 2025-3-25 12:42:32 | 显示全部楼层
    路过,支持一下
    http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
    严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    1楼
    2楼

    手机版|晓枫资讯--科技资讯社区 本站已运行

    CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

    晓枫资讯--科技资讯社区

    本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

    如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

    Powered by Discuz! X3.5

    快速回复 返回顶部 返回列表