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转换小游戏的步骤,遇到问题的解决方法,以及简单的性能测试对比 微信小游戏的限制 微信小游戏对程序包体大小有严格限制…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
