C#之扩展方法详解

news2025/1/24 11:44:44

前言:

我们想要向一个类型中添加方法,可以通过以下两种方式:

1.修改源代码。

2.在派生类中定义新的方法。

但是这两种方式都有缺点,1如果是别人的代码,你对其直接进行修改,可能破坏代码的完整性,使代码无法编译,2会增加代码的维护成本,修改功能时父类子类可能都要修改

1.扩展方法概述和基本准则

(1).C#只支持扩展方法,不支持扩展属性、扩展事件、扩展操作符等。

 (2).扩展方法(第一个参数前面是this的方法)必须在非泛型的静态类中声明,扩展方法必须有一个参数,而且只有第一个参数使用this标记。

 (3).用一个扩展方法扩展一个类型时,同时也扩展了派生类型。 

2.扩展方法应用

namespace HelloWorld//命名空间
{
    public class Student
    {
        public void FunctionA()
        {
            Console.WriteLine("我是方法A");
        }

    }

    public static class Extension
    {
        public static void FunctionB(this Student myStudent, int a)
        {
            Console.WriteLine("我是Student类的扩展方法B,参数是" + a);
        }
    }

    class ExtMethodDemo
    {
        static void Main(string[] args)
        {
            Student a=new Student();
            a.FunctionB(5);
        }
    }
}

打印结果:

扩展方法扩展的不仅仅可以是引用类型,也可以是值类型,附带一个官方的例子

3.扩展方法本质

         “扩展方法”是C#独有的一种方法,在扩展方法中会使用ExtensionAttribute这个attribute。

        C#一旦使用this关键字标记了某个静态方法的第一个参数,编译器就会在内部向该方法应用一个定制的attribute,这个attribute会在最终生成的文件的元数据中持久性的存储下来,此属性在System.Core dll程序集中。

        任何静态类只要包含了至少一个扩展方法,它的元数据中也会应用这个attribute,任何一个程序集包含了至少一个符合上述特点的静态类,它的元数据也会应用这个attribute。如果代码用了一个不存在的实例方法,编译器会快速的扫描引用的所有程序集,判断它们哪些包含了扩展方法,然后,在这个程序集中,可以扫描包含了扩展方法的静态类。

        如果同一个命名空间中的两个类含有扩展类型相同的方法,就没有办法做到只用其中一个类中的扩展方法。为了通过类型的简单名称(没有命名空间前缀)来使用类型,可以导入该类型所有在的命名空间,但这样做的时候,你没有办法阻止那个命名空间中的扩展方法也被导入进来。

就比如说:

  当编译看到以上述代码,编译器分两步工作:

  (1) 编译器检查a当前类型,也就是Student类以及Student任何基类是否具有所匹配的名为FunctionB包含一个int参数的函数,如果找到,则生成IL代码并Call它;

  (2) 如果没有找到匹配的方法,就继续检查是否有任何静态类定义了名为FunctionB的静态方法,并且这个方法必须第一个参数是用this关键字修饰,参数类型为Student的。找到时生成相应的IL代码来调用它。

        所以也解释了为什么扩展类必须是静态非泛型的,因为你必须保证在编译阶段,Student能找到它匹配的方法,而泛型是在程序运行时才能确定方法。

官方文档链接:扩展方法 - C# 编程指南 - C# | Microsoft Learn

参考链接:https://www.cnblogs.com/yuer20180726/p/10901123.html

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

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

相关文章

高项备考葵花宝典-项目进度管理输入、输出、工具和技术(下,很详细考试必过)

项目进度管理的目标是使项目按时完成。有效的进度管理是项目管理成功的关键之一,进度问题在项目生命周期内引起的冲突最多。 小型项目中,定义活动、排列活动顺序、估算活动持续时间及制定进度模型形成进度计划等过程的联系非常密切,可以视为一…

【MySQL】MySQL的varchar字段最大长度是65535?

在MySQL建表sql里,我们经常会有定义字符串类型的需求。 CREATE TABLE `user` ( `name` varchar(100) NOT NULL DEFAULT COMMENT 名字) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ; 比方说user表里的名字,就是个字符串。MySQL里有两个类型比较适合这个场景。 char和varchar。…

Nexus搭建npm私库(角色管理、上传脚本)

安装Nexus 官网下载 https://www.sonatype.com/products/sonatype-nexus-oss-download 进入官网下载,最新下载方式需要输入个人信息才能下载了 选择对应的系统进行下载 Windows 推荐也下载 UNIX 版本(Windows 版本配置比较难改) 如果没有下…

TrustZone之SMC异常

作为支持两个安全状态的一部分,该架构包括了Secure Monitor Call(SMC)指令。执行SMC会引发Secure Monitor Call异常,该异常目标是EL3。 通常,SMC用于请求服务,可以是来自驻留在EL3中的固件,也可…

Android之Binder原理剖析

一:Binder的全面介绍 binder的出现 George Hoffman当时任Be公司的工程师,他启动了一个名为OpenBinder 的项目,在Be公司被ParmSource公司收购后, OpenBinder 由Dinnie Hackborn继续开发,后来成为管理ParmOS6 Cobalt O…

springboot_ssm_java学位论文盲审系统

本系统主要实现用户登录验证,用户使用邮箱,密码和选择身份进行登录,用户查看个人中心,提交论文,发表留言和问题反馈。用户在线注册。学生模块功能实现:学生注册,查看信息,修改资料&a…

Vue项目中实现浏览器标签页名字的动态修改

修改router/index.js文件 路由条目下面添加meta属性 meta:{title:DevOps运维平台 }示例 使用Vue的全局守卫函数beforeEach,在路由切换前动态修改浏览器标签页名字 router.beforeEach((to,from,next) > {document.title to.meta.titlenext() })

HSV算法及其改进 (附代码)

1.HSV HSV是一种颜色空间,它由色相(Hue)、饱和度(Saturation)和明度(Value)三个参数组成。HSV模型中,色相表示颜色的种类,饱和度表示颜色的纯度,明度表示颜色…

YOLOv8 YoLov8l 模型输出及水果识别

🍨 本文为[🔗365天深度学习训练营学习记录博客 🍦 参考文章:365天深度学习训练营 🍖 原作者:[K同学啊 | 接辅导、项目定制] 🚀 文章来源:[K同学的学习圈子](https://www.yuque.com/m…

认识线程和创建线程

目录 1.认识多线程 1.1线程的概念 1.2进程和线程 1.2.1进程和线程用图描述关系 1.2.2进程和线程的区别 1.3Java 的线程和操作系统线程的关系 2.创建线程 2.1继承 Thread 类 2.2实现 Runnable 接口 2.3匿名内部类创建 Thread 子类对象 2.4匿名内部类创建 Runnable 子类对…

LLM之Agent(五)| AgentTuning:清华大学与智谱AI提出AgentTuning提高大语言模型Agent能力

​论文地址:https://arxiv.org/pdf/2310.12823.pdf Github地址:https://github.com/THUDM/AgentTuning 在ChatGPT带来了大模型的蓬勃发展,开源LLM层出不穷,虽然这些开源的LLM在各自任务中表现出色,但是在真实环境下作…

1.cloud-微服务架构编码构建

1.微服务cloud整体聚合父工程 1.1 New Project 1.2 Maven选版本 1.3 字符编码 1.4 注解生效激活 主要为lombok中的Data 1.5 java编译版本选8 1.6 File Type过滤 *.hprof;*.idea;*.iml;*.pyc;*.pyo;*.rbc;*.yarb;*~;.DS_Store;.git;.hg;.svn;CVS;__pycache__;_svn;vssver.scc;v…

嵌入式C语言代码的基本编写规范要求

编码规范,没有最好,只有最合适,有但不执行不如没有。1 编码原则 1.1 可读性原则 (1)清晰第一 清晰性是易于维护程序必须具备的特征。维护期变更代码的成本远远大于开发期,编写程序应该以人为本&#xff0c…

vue3中子组件调用父组件的方法

<script lang"ts" setup>前提 父组件&#xff1a; 子组件&#xff1a; const emit defineEmits([closeson]) 在子组件的方法中使用&#xff1a; emit(closeson)

Spring Boot学习随笔- 集成JSP模板(配置视图解析器)、整合Mybatis(@MapperScan注解的使用)

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第五章、JSP模板集成 5.1 引入JSP依赖 <!--引入jsp解析依赖--> <!--C标签库--> <dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version&…

ES6之Symbol

ES6中为我们新增了一个原始数据类型Symbol&#xff0c;让我为大家介绍一下吧&#xff01; Symbol它表示是独一无二的值 Symbol要如何创建 第一种创建方式&#xff1a; let sy Symbol()第二种创建方式&#xff1a; let sy Symbol.for()具体独一无二在哪呢&#xff1f;它们的地…

【MyBatis系列】MyBatis字符串问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Java中的IO流①——IO流的体系、字节流、try...catch异常处理

概述 IO流的分类 IO流的体系 这四个类都是抽象类&#xff0c;所以需要实现类对象才能使用---> 字节流 FileInputStream--> 书写细节 代码示范 此时文件a.txt内容为abcde 使用char强转和read方法调用五次read方法--> public static void main(String[] args) throws IO…

JavaScript-节点操作

节点操作 DOM节点 DOM节点&#xff1a;DOM树里每一个内容都称之为节点 节点类型&#xff1a; 元素节点 所有的标签 比如body、divhtml时跟节点 属性节点 所有的属性&#xff0c;比如href 文本节点 所有的文本 其他 查找节点 节点的关系&#xff1a;针对的找亲戚返回的都是…

redis中缓存雪崩,缓存穿透,缓存击穿等

缓存雪崩 由于原有缓存失效&#xff08;或者数据未加载到缓存中&#xff09;&#xff0c;新缓存未到期间&#xff08;缓存正常从Redis中获取&#xff0c;如下图&#xff09;所有原本应该访问缓存的请求都去查询数据库了&#xff0c;而对数据库CPU和内存造成巨大压力&#xff0c…