C# 继承,抽象,接口,泛型约束,扩展方法
文章目录
- 前言
- 模拟需求
- 场景模拟
- 重复性高的需求
- 初始类结构
- 继承优化
- 抽象类
- 需求1:打印CreateTime
- 方法1:使用重载
- 方法2:基类函数
- 方法3:泛型约束
- 方法3.1:普通泛型方法
- 方法3.2:高级泛型约束,扩展方法
- 总结
- 番外篇:泛型方法和接口
- 泛型约束抽象接口
- 总结
前言
以前计算机本科学习的时候,我就知道了继承,重载,接口,抽象,泛型等概念。本章优先讲解继承,接口,抽象,泛型这一组概念。如果说继承,抽象只是为了标准化代码,规范程序编写的话,那么泛型约束就是给于了继承抽象这个写法的必要性。
c# 继承
浅谈C#中的抽象类(abstract)和接口(interface)
C#泛型约束
模拟需求
因为我干的是上位机工作,这里我就讲解一下我用到的场景。上位机的代码重复性很高,泛型约束就是用于解决此类问题。
场景模拟
我是A公司,我有多种(为了简单按两种算)产品,这2种产品有一下两个特质
- 每个产品存数据库的字段有完全相同的3个字段
- Id:数据库Id
- DeivceId:设备唯一Id,全部种类产品唯一的Id。
- CreateTime:数据录入数据库时间
重复性高的需求
我们现在有个需求,给每个类添加一个打印CreateTime的方法
初始类结构
public class DeviceA{public string DeviceId { get; set; }public long Id { get; set; } public DateTime CreateTime { get; set; }public string ValueA { get; set; }}public class DeviceB{public string DeviceId { get; set; }public long Id { get; set; }public DateTime CreateTime { get; set; }public string ValueB { get; set; }}
继承优化
继承的目的就是为了减少重复的字段
public class DeviceA:DeviceBase
{public string ValueA { get; set; }
}public class DeviceB : DeviceBase
{public string ValueB { get; set; }}
/// <summary>
/// 使用基类优化代码
/// </summary>
public class DeviceBase
{public string DeviceId { get; set; }public long Id { get; set; }public DateTime CreateTime { get; set; }
}
抽象类
我们也可以在基类上面添加abstract关键字
public abstract class DeviceBase
{public string DeviceId { get; set; }public long Id { get; set; }public DateTime CreateTime { get; set; }}
区别就是抽象类无法实例化

那么抽象类的意义就是为了告诉你,我的基类是没有任何实际意义的,我单纯就是为了继承用的
需求1:打印CreateTime
方法1:使用重载
static void Main(string[] args)
{var DeviceA = new DeviceA() { CreateTime = DateTime.Now};var DeviceB = new DeviceB() { CreateTime = DateTime.Now };PrintCreateTime(DeviceA);PrintCreateTime(DeviceB);
}
public static void PrintCreateTime(DeviceA deviceA)
{Console.WriteLine($"{deviceA.CreateTime}");
}public static void PrintCreateTime(DeviceB deviceB)
{Console.WriteLine($"{deviceB.CreateTime}");
}
方法2:基类函数
internal class Program
{static void Main(string[] args){var DeviceA = new DeviceA() { CreateTime = DateTime.Now};var DeviceB = new DeviceB() { CreateTime = DateTime.Now };DeviceA.PrintCreateTime();DeviceB.PrintCreateTime();}}/// <summary>
/// 使用基类优化代码
/// </summary>
public class DeviceBase
{·······public void PrintCreateTime(){Console.WriteLine(CreateTime.ToString());}
}
方法3:泛型约束
方法3.1:普通泛型方法
static void Main(string[] args){var DeviceA = new DeviceA() { CreateTime = DateTime.Now};var DeviceB = new DeviceB() { CreateTime = DateTime.Now };PrintCreateTime(DeviceA);PrintCreateTime(DeviceB);}/// <summary>/// 泛型约束DeviceBase基类/// </summary>/// <typeparam name="T"></typeparam>/// <param name="model"></param>public static void PrintCreateTime<T>(T model)where T : DeviceBase{Console.WriteLine(model.CreateTime.ToString());}
方法3.2:高级泛型约束,扩展方法
C#小轮子:扩展方法
internal class Program
{static void Main(string[] args){var DeviceA = new DeviceA() { CreateTime = DateTime.Now};var DeviceB = new DeviceB() { CreateTime = DateTime.Now };DeviceA.PrintCreateTime();DeviceB.PrintCreateTime();}}public static class DeviceExtension
{/// <summary>/// 扩展方法是更高级的泛型方法,但是需要一个静态类扩展/// </summary>/// <typeparam name="T"></typeparam>/// <param name="model"></param>public static void PrintCreateTime<T>(this T model) where T : DeviceBase{Console.WriteLine(model.CreateTime.ToString());}
}
总结
| 优点 | 缺点 | |
|---|---|---|
| 重载 | 更灵活,每个类都可以定制 | 重复性高 |
| 基类方法 | 降低重复度 | 耦合度高,过多会导致基类臃肿,不符合属性类规范 |
| 泛型约束 | 降低重复度,耦合度低,易于扩展。 | 不能访问基类以外的属性 |
| 扩展方法 | 最强的扩展性,完美代替基类方法 | 需要单独一个静态类 |
属性类:是我自己的规范。就是基础的属性类只有属性和构造函数,没有方法。
番外篇:泛型方法和接口
有些时候我们设备类的逻辑特别的复杂,比如每个产品都有四个方法:
- 连接
- 发送
- 接受
- 关闭连接
public interface IDevice
{public void Connect();public void Send();public void Recive();public void Close();}
public class DeviceA : DeviceBase, IDevice
{public string ValueA { get; set; }public void Close(){throw new NotImplementedException();}public void Connect(){throw new NotImplementedException();}public void Recive(){throw new NotImplementedException();}public void Send(){throw new NotImplementedException();}
}public class DeviceB : DeviceBase, IDevice
{public string ValueB { get; set; }public void Close(){throw new NotImplementedException();}public void Connect(){throw new NotImplementedException();}public void Recive(){throw new NotImplementedException();}public void Send(){throw new NotImplementedException();}
}
泛型约束抽象接口
static void Main(string[] args)
{var DeviceA = new DeviceA() { CreateTime = DateTime.Now};var DeviceB = new DeviceB() { CreateTime = DateTime.Now };GetData(DeviceA);GetData(DeviceB);
}/// <summary>
/// 泛型约束也可以约束接口
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="model"></param>
public static void GetData<T>(T model) where T : IDevice
{model.Connect();model.Send();model.Recive();model.Close();
}
总结
不是说只能用泛型约束去解决问题,而且泛型约束和扩展方法更具有扩展性,低耦合的特点。大家可以根据自己代码的习惯选择性的使用。
相关文章:
C# 继承,抽象,接口,泛型约束,扩展方法
文章目录 前言模拟需求场景模拟重复性高的需求初始类结构继承优化抽象类 需求1:打印CreateTime方法1:使用重载方法2:基类函数方法3:泛型约束方法3.1:普通泛型方法方法3.2:高级泛型约束,扩展方法…...
mysql的备份和恢复
备份:完全备份 增量备份 完全备份:将整个数据库完整的进行备份 增量备份:在完全备份的基础之上,对后续新增的内容进行备份 备份的需求 1、在生产环境中,数据的安全至关重要,任何数据的都可能产生非常严重…...
【机器学习3】有监督学习经典分类算法
1 支持向量机 在现实世界的机器学习领域, SVM涵盖了各个方面的知识, 也是面试题目中常见的基础模型。 SVM的分类结果仅依赖于支持向量,对于任意线性可分的两组点,它 们在SVM分类的超平面上的投影都是线性不可分的。 2逻辑回归 …...
lv11 嵌入式开发 计算机硬件基础 1
目录 1 导学 1.1回顾及导学 1.2 嵌入式系统分层 1.3 linux底层开发 2 ARM体系结构与接口技术课程导学 3 计算机基础 3.1 计算机的进制 3.2 计算机组成 3.3 总线 4 多级存储结构与地址空间 4.1 多级存储概念 4.2 地址空间 5 CPU工作原理 6 练习 1 导学 1.1回顾及导…...
【Linux】vim
文章目录 一、vim是什么?二 、命令模式三、插入模式四、底行模式五、vim配置 一、vim是什么? Vim是一个强大的文本编辑器,它是Vi的增强版,支持多种语法高亮、插件扩展、多模式操作等功能。Vim有三种基本的工作模式:命…...
cstring函数
string 1.char str[]类型 fgets(s,10000,stdin) cin.getline(cin,10000) strlen(str) sizeof 求静态数组长度 2.string类型 getline(cin,a) cin.getline(cin,10000) str.lenth() str.size() cin 遇到空格就停止 3.gets 函数 char str[20]; gets(str); 4.puts 函…...
【owt】p2p client mfc 工程梳理
1年前构建的,已经搞不清楚了。所以梳理下,争取能用较新的webrtc版本做测试。最早肯定用这个测试跑通过 【owt】p2p Signaling Server 运行、与OWT-P2P-MFC 交互过程及信令分析官方的mfc客户端 估计是构造了多个不同的webrc版本的客户端...
pandas教程:Hierarchical Indexing 分层索引、排序和统计
文章目录 Chapter 8 Data Wrangling: Join, Combine, and Reshape(数据加工:加入, 结合, 变型)8.1 Hierarchical Indexing(分层索引)1 Reordering and Sorting Levels(重排序和层级排序)2 Summa…...
Redis 扩展 RedisBloom 插件,解决缓存击穿、穿透
文章目录 一、概述二、编译准备2.1 升级 make2.2 安装 Python3 三、编译 RedisBloom四、测试 RedisBloom五、应用场景5.1 缓存击穿5.2 缓存穿透5.3 原理总结 六、存在的问题 如果您对Redis的了解不够深入请关注本栏目,本栏目包括Redis安装,Redis配置文件…...
VBA技术资料MF80:选择文件及文件夹
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。我的教程一共九套,分为初级、中级、高级三大部分。是对VBA的系统讲解,从简单的入门,到…...
网络层:控制平面
路由选择算法 路由选择算法就是为了在端到端的数据传输中,选择路径上路由器的最好的路径。通常,一条好的路径指具有最低开销的路径。最低开销路径是指源和目的地之间具有最低开销的一条路。 根据集中式还是分散式来划分 集中式路由选择算法:…...
Ubuntu 系统内核 kernel panic
Ubuntu 系统内核 kernel panic 不能进入系统:报错end kernel panic -not syncing: attemped to kill init! exit code 0x00000100 系统启动的时候,按下‘e’键进入grub编辑界面,编辑grub菜单,选择“kernel /vmlinuz-XXXXro root…...
【flink】RowData copy/clone方式
说明:一般用户常用的是GenericRowData。flink内部则多使用BinaryRowData。 方法一、循环解决(不推荐): 代码较为复杂需要根据RowType获取到内部fields的logicalType,再使用RowData.createFieldGetter方法创建fieldGetters。 public static …...
网页图标工具
工具地址...
掌动智能:功能测试及拨测主要功能
在企业中对于功能测试及拨测而言,用户只需提供应用包和产品文档,由资深测试专家设计并执行测试,覆盖核心场景,包含特定业务流程以及行业通用特殊场景,支持需求定制。 执行过程严格监控,依据应用功能和业务需…...
第11章 Java集合(二)
目录 内容说明 章节内容 一、Set接口 二、HashSet集合 三、LinkedHashSet集合 四、TreeSet集合...
Transformer和ELMo模型、word2vec、独热编码(one-hot编码)之间的关系
下面简要概述了Transformer和ELMo模型、word2vec、独热编码(one-hot编码)之间的关系: 独热编码(One-hot Encoding)是一种最基本的词表示方法,将词表示为高维稀疏向量。它与ELMo、word2vec和Transformer的关…...
您与1秒钟测量两千个尺寸之间仅差一台智能测径仪!
随着产线的发展,自动化程度越来越高,生产速度越来越快,人们对产品的品质要求越来越高,对检测也提出了更高的要求。传统的检测与测量手段已经很难满足测量效率要求,业内迫切需要一种新型高效率的测量设备。 产线多种多样…...
k8s之service五种负载均衡byte的区别
1,什么是Service? 1.1 Service的概念 在k8s中,service 是一个固定接入层,客户端可以通过访问 service 的 ip 和端口访问到 service 关联的后端pod,这个 service 工作依赖于在 kubernetes 集群之上部署的一个附件&a…...
Unity项目转微信小游戏保姆教程,繁杂问题解决,及微信小游戏平台简单性能测试
前言 借着某人需求,做了一波简单的技术调研:将Unity项目转换为微信小游戏。 本文主要内容:Unity转换小游戏的步骤,遇到问题的解决方法,以及简单的性能测试对比 微信小游戏的限制 微信小游戏对程序包体大小有严格限制…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
