C#中扩展方法和钩子机制使用

news2025/4/19 23:31:34

1.扩展方法:

扩展方法允许向现有类型 “添加” 方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像实例方法一样进行调用。

使用场景:

1.当无法修改某个类的源代码,但又希望为该类添加一些实用方法时,扩展方法就非常有用。
2.为第三方库中的类型添加额外的功能。

实现:

1.基础实现

public class ExtensionTest : MonoBehaviour
{
    void Start()
    {
        MyClass obj = new MyClass(5);
        // 可以像调用实例方法一样调用扩展方法
        int result = obj.DoubleValue();
        Debug.Log($"Double value: {result}");
    }
}

// 定义一个简单的类
public class MyClass
{
    public int Value { get; set; }

    public MyClass(int value)
    {
        Value = value;
    }
}

// 扩展方法必须定义在静态类中
public static class MyClassExtensions
{
    // 扩展方法必须是静态方法,且第一个参数使用 this 关键字指定要扩展的类型
    public static int DoubleValue(this MyClass myClass)
    {
        return myClass.Value * 2;
    }
}

 结果:

2.链式扩展

public class ExtensionTest : MonoBehaviour
{
    void Start()
    {
        Person person = new Person("John", 25);
        // 链式调用扩展方法
        person.SetName("Alice").SetAge(30).PrintInfo();
    }
}

// 定义一个简单的类
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public void PrintInfo()
    {
        Debug.Log($"Name: {Name}, Age: {Age}");
    }
}

// 扩展方法类
public static class PersonExtensions
{
    // 扩展方法:设置姓名
    public static Person SetName(this Person person, string name)
    {
        person.Name = name;
        return person;
    }

    // 扩展方法:设置年龄
    public static Person SetAge(this Person person, int age)
    {
        person.Age = age;
        return person;
    }
}

结果:

 

2.钩子机制:

在 C# 中,钩子通常指的是在程序执行过程中预留的一些 “可插入点”,允许开发者在特定的时机插入自定义的逻辑。常见的实现方式有事件(Event)、抽象方法、委托等

使用场景:

1.当你需要在某个操作的前后执行自定义逻辑时,可以使用钩子。
2.实现插件化架构,允许开发者在系统的某些关键位置插入自定义的功能。

实现:

1.虚方法钩子:基类定义一个虚方法,该方法可以包含默认的实现逻辑,也可以为空。派生类重写这个虚方法,在其中添加自定义的逻辑。基类在执行某个算法时,会调用这个虚方法,这样派生类就可以在这个 “钩子点” 上插入自己的代码。

public class HookTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 创建魔法师角色
        GameCharacter mage = new Mage();
        mage.Attack();

        Console.WriteLine();

        // 创建战士角色
        GameCharacter warrior = new Warrior();
        warrior.Attack();
    }
}

public class HookTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // 创建魔法师角色
        GameCharacter mage = new Mage();
        mage.Attack();

        Console.WriteLine();

        // 创建战士角色
        GameCharacter warrior = new Warrior();
        warrior.Attack();
    }
}

// 基类:游戏角色
public class GameCharacter
{
    // 虚方法,作为钩子
    public virtual void SpecialAbility()
    {
        Debug.Log("No special ability.");
    }

    // 角色的攻击方法,会调用钩子方法
    public void Attack()
    {
        Debug.Log("Character attacks!");
        SpecialAbility();
    }
}

// 派生类:魔法师
public class Mage : GameCharacter
{
    // 重写虚方法,添加自定义逻辑
    public override void SpecialAbility()
    {
        Debug.Log("Mage casts a fireball!");
    }
}

// 派生类:战士
public class Warrior : GameCharacter
{
    // 重写虚方法,添加自定义逻辑
    public override void SpecialAbility()
    {
        Debug.Log("Warrior uses a powerful shield bash!");
    }
}

结果:

2.事件钩子​:

public class HookTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        MyProcessor processor = new MyProcessor();

        // 订阅事件,插入自定义逻辑
        processor.BeforeProcess += (sender, e) =>
        {
            Debug.Log("Before process: Custom logic executed.");
        };

        processor.AfterProcess += (sender, e) =>
        {
            Debug.Log("After process: Custom logic executed.");
        };

        processor.Process();
    }
}

// 定义一个包含钩子的类
public class MyProcessor
{
    // 定义事件,作为钩子
    public event EventHandler BeforeProcess;
    public event EventHandler AfterProcess;

    public void Process()
    {
        // 在处理前触发事件
        BeforeProcess?.Invoke(this, EventArgs.Empty);

        Debug.Log("Processing...");

        // 在处理后触发事件
        AfterProcess?.Invoke(this, EventArgs.Empty);
    }
}

结果:

总结:

通过合理使用扩展方法和钩子方法,可以在保持外观模式简洁性的同时,提供强大的扩展能力。
1.扩展方法​​适合添加​​横向功能​​(如日志、监控)。
​2.​虚方法钩子​​适合调整​​核心流程​​
​​3.事件机制​​适合实现​​观察者模式​​的松散耦合
4.优先选择​​组合​​而非多层继承

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12的网络结构图

文章目录 一、YOLOv5二、YOLOv6三、YOLOv7四、YOLOv8五、YOLOv9六、YOLOv10七、YOLOv11八、YOLOv12九、目标检测系列文章 本文将给出YOLO各版本(YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12)网络结构图的绘制方法及图。本文所展…

03 UV

04 Display工具栏_哔哩哔哩_bilibili 讲的很棒 ctrlMMB 移动点 s 打针 ss 批量打针

AIGC-几款本地生活服务智能体完整指令直接用(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…

C#/.NET/.NET Core拾遗补漏合集(25年4月更新)

前言 在这个快速发展的技术世界中,时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节,以帮助大家更全面地了解这些技术栈的特性和发展方向。 ✍C#/.NET/.N…

MySQL性能调优(三):MySQL中的系统库(简介、performance_schema)

文章目录 MySQL性能调优数据库设计优化查询优化配置参数调整硬件优化 1.MySQL中的系统库1.1.系统库简介1.2.performance_schema1.2.1.什么是performance_schema1.2.2.performance_schema使用1.2.3.检查当前数据库版本是否支持1.2.4.performance_schema表的分类1.2.5.performanc…

印度zj游戏出海代投本土网盟广告核心优势

印度游戏出海代投本土网盟广告的核心优势包括: 本土化广告策略:针对印度市场的特点,定制本土化的广告策略,吸引更多印度用户的关注和参与。 深度了解印度市场:对印度文化、消费习惯、网络使用习惯等有深入了解&#x…

NO.97十六届蓝桥杯备战|数论板块-最大公约数和最小公倍数|欧几里得算法|秦九韶算法|小红的gcd(C++)

约数和倍数 如果a 除以b 没有余数,那么a 就是b 的倍数,b 就是a 的约数,记作b ∣ a 。 约数,也称因数。 最⼤公约数和最⼩公倍数 最⼤公约数Greatest Common Divisor,常缩写为gcd。 ⼀组整数的公约数,是…

《软件设计师》复习笔记(11.6)——系统转换、系统维护、系统评价

目录 一、遗留系统(Legacy System) 定义: 特点: 演化策略(基于价值与技术评估): 高水平 - 低价值: 高水平 - 高价值: 低水平 - 低价值: 低水平 - 高价…

人像面部关键点检测

此工作为本人近期做人脸情绪识别,CBAM模块前是否能加人脸关键点检测而做的尝试。由于创新点不是在于检测点的标注,而是CBAM的改进,因此,只是借用了现成库Dilb与cv2进行。 首先,下载人脸关键点预测模型:Index of /file…

EDID结构

EDID DDC通讯中传输显示设备数据 VGA , DVI 的EDID由128字节组成,hdmi的EDID增加扩展块128字节。扩展快的内容主要是和音频属性相关的,DVI和vga没有音频,hdmi自带音频,扩展快数据规范按照cea-861x标准。 Edid为了让pc或其他的图像…

文件包含(详解)

文件包含漏洞是一种常见的Web安全漏洞,其核心在于应用程序未对用户控制的文件路径或文件名进行严格过滤,导致攻击者能够包含并执行任意文件(包括本地或远程恶意文件)。 1. 文件包含原理 动态文件包含机制 开发者使用动态包含函数…

《SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战》​

🌟 ​大家好,我是摘星!​ 🌟 今天为大家带来的是Scheduled和Quartz对比分析: 新手常见困惑: 刚学SpringBoot时,我发现用Scheduled写定时任务特别简单。但当我看到同事在项目里用Quartz时&…

安装fvm可以让电脑同时管理多个版本的flutter、flutter常用命令、vscode连接模拟器

打开 PowerShellfvm安装 dart pub global activate fvm安装完成后,如果显示FVM无法识别,那么需要去添加环境变量path添加这个:C:\Users\Administrator\AppData\Local\Pub\Cache\bin 常用命令 fvm releases 查看用户可以装的flutter版本fvm l…

Kafka系列之:计算kafka集群topic占的存储大小

Kafka系列之:计算kafka集群topic占的存储大小 topic存储数据格式统计topic存储大小定时统计topic存储大小topic存储数据格式 单位是字节大小 size_bytes{directory="/data/datum/kafka/optics-all" } 782336计算topic存储大小脚本逻辑是: 计算指定目录或文件的大小…

智谱AI大模型免费开放:开启AI创作新时代

文章摘要:近日,国内领先的人工智能公司智谱AI宣布旗下多款大模型服务免费开放,这一举措标志着大模型技术正式迈入普惠阶段。本文将详细介绍智谱AI此次开放的GLM-4 等大模型,涵盖其主要功能、技术特点、使用步骤以及应用场景&#…

T1结构像+RS-fMRI影像处理过程记录(数据下载+Matlab工具箱+数据处理)

最近需要仿真研究T1结构像RS-fMRI影像融合处理输出目标坐标的路线可行性。就此机会记录下来。 为了完成验证目标处理,首先需要有数据,然后需要准备对应的处理平台和工具箱,进行一系列。那么开始记录~ 前言: 为了基于种子点的功能连…

【前端基础】--- HTML

个人主页  :  9ilk    专栏  :  前端基础 文章目录 🏠 初识HTML🏠 HTML结构认识HTML标签HTML文件基本结构标签层次结构快速生成代码框架 🏠 HTML常见标签注释标签标题标签 h1-h6段落标签 p换行标签 br格式化标签图片标签 img超链接标签…

黑马V11版 最新Java高级软件工程师课程-JavaEE精英进阶课

课程大小:60.2G 课程下载:https://download.csdn.net/download/m0_66047725/90615581 更多资源下载:关注我 阶段一 中台战略与组件化开发专题课程 阶段二 【物流行业】品达物流TMS 阶段三 智牛股 阶段四 千亿级电商秒杀解决方案专题 …

C#插件与可扩展性

外接程序为主机应用程序提供了扩展功能或服务。.net framework提供了一个编程模型,开发人员可以使用该模型来开发加载项并在其主机应用程序中激活它们。该模型通过在主机和外接程序之间构建通信管道来实现此目的。该模型是使用: System.AddIn, System.AddIn.Hosting, System.…

CVPR‘25 | 高文字渲染精度的商品图文海报生成

本文分享阿里妈妈智能创作与AI应用团队在图文广告创意方向上提出的商品图文海报生成模型,通过构建字符级视觉表征作为控制信号,可以实现精准的图上中文逐像素生成。基于该项工作总结的论文已被 CVPR 2025录用,并在阿里妈妈业务场景落地&#…