当前位置: 首页 > news >正文

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&#xff1a;打印CreateTime方法1&#xff1a;使用重载方法2&#xff1a;基类函数方法3&#xff1a;泛型约束方法3.1&#xff1a;普通泛型方法方法3.2&#xff1a;高级泛型约束&#xff0c;扩展方法…...

mysql的备份和恢复

备份&#xff1a;完全备份 增量备份 完全备份&#xff1a;将整个数据库完整的进行备份 增量备份&#xff1a;在完全备份的基础之上&#xff0c;对后续新增的内容进行备份 备份的需求 1、在生产环境中&#xff0c;数据的安全至关重要&#xff0c;任何数据的都可能产生非常严重…...

【机器学习3】有监督学习经典分类算法

1 支持向量机 在现实世界的机器学习领域&#xff0c; SVM涵盖了各个方面的知识&#xff0c; 也是面试题目中常见的基础模型。 SVM的分类结果仅依赖于支持向量&#xff0c;对于任意线性可分的两组点&#xff0c;它 们在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是什么&#xff1f;二 、命令模式三、插入模式四、底行模式五、vim配置 一、vim是什么&#xff1f; Vim是一个强大的文本编辑器&#xff0c;它是Vi的增强版&#xff0c;支持多种语法高亮、插件扩展、多模式操作等功能。Vim有三种基本的工作模式&#xff1a;命…...

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&#xff08;数据加工&#xff1a;加入, 结合, 变型&#xff09;8.1 Hierarchical Indexing&#xff08;分层索引&#xff09;1 Reordering and Sorting Levels&#xff08;重排序和层级排序&#xff09;2 Summa…...

Redis 扩展 RedisBloom 插件,解决缓存击穿、穿透

文章目录 一、概述二、编译准备2.1 升级 make2.2 安装 Python3 三、编译 RedisBloom四、测试 RedisBloom五、应用场景5.1 缓存击穿5.2 缓存穿透5.3 原理总结 六、存在的问题 如果您对Redis的了解不够深入请关注本栏目&#xff0c;本栏目包括Redis安装&#xff0c;Redis配置文件…...

VBA技术资料MF80:选择文件及文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…...

网络层:控制平面

路由选择算法 路由选择算法就是为了在端到端的数据传输中&#xff0c;选择路径上路由器的最好的路径。通常&#xff0c;一条好的路径指具有最低开销的路径。最低开销路径是指源和目的地之间具有最低开销的一条路。 根据集中式还是分散式来划分 集中式路由选择算法&#xff1a…...

Ubuntu 系统内核 kernel panic

Ubuntu 系统内核 kernel panic 不能进入系统&#xff1a;报错end kernel panic -not syncing: attemped to kill init! exit code 0x00000100 系统启动的时候&#xff0c;按下‘e’键进入grub编辑界面&#xff0c;编辑grub菜单&#xff0c;选择“kernel /vmlinuz-XXXXro root…...

【flink】RowData copy/clone方式

说明&#xff1a;一般用户常用的是GenericRowData。flink内部则多使用BinaryRowData。 方法一、循环解决(不推荐)&#xff1a; 代码较为复杂需要根据RowType获取到内部fields的logicalType&#xff0c;再使用RowData.createFieldGetter方法创建fieldGetters。 public static …...

网页图标工具

工具地址...

掌动智能:功能测试及拨测主要功能

在企业中对于功能测试及拨测而言&#xff0c;用户只需提供应用包和产品文档&#xff0c;由资深测试专家设计并执行测试&#xff0c;覆盖核心场景&#xff0c;包含特定业务流程以及行业通用特殊场景&#xff0c;支持需求定制。 执行过程严格监控&#xff0c;依据应用功能和业务需…...

第11章 Java集合(二)

目录 内容说明 章节内容 一、Set接口 二、HashSet集合 三、LinkedHashSet集合 四、TreeSet集合...

Transformer和ELMo模型、word2vec、独热编码(one-hot编码)之间的关系

下面简要概述了Transformer和ELMo模型、word2vec、独热编码&#xff08;one-hot编码&#xff09;之间的关系&#xff1a; 独热编码&#xff08;One-hot Encoding&#xff09;是一种最基本的词表示方法&#xff0c;将词表示为高维稀疏向量。它与ELMo、word2vec和Transformer的关…...

您与1秒钟测量两千个尺寸之间仅差一台智能测径仪!

随着产线的发展&#xff0c;自动化程度越来越高&#xff0c;生产速度越来越快&#xff0c;人们对产品的品质要求越来越高&#xff0c;对检测也提出了更高的要求。传统的检测与测量手段已经很难满足测量效率要求&#xff0c;业内迫切需要一种新型高效率的测量设备。 产线多种多样…...

k8s之service五种负载均衡byte的区别

1&#xff0c;什么是Service&#xff1f; 1.1 Service的概念​ 在k8s中&#xff0c;service 是一个固定接入层&#xff0c;客户端可以通过访问 service 的 ip 和端口访问到 service 关联的后端pod&#xff0c;这个 service 工作依赖于在 kubernetes 集群之上部署的一个附件&a…...

Unity项目转微信小游戏保姆教程,繁杂问题解决,及微信小游戏平台简单性能测试

前言 借着某人需求&#xff0c;做了一波简单的技术调研&#xff1a;将Unity项目转换为微信小游戏。 本文主要内容&#xff1a;Unity转换小游戏的步骤&#xff0c;遇到问题的解决方法&#xff0c;以及简单的性能测试对比 微信小游戏的限制 微信小游戏对程序包体大小有严格限制…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...