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

C#抽象类和虚方法的作用是什么?

抽象类 (abstract class):

  • 不能直接实例化,只能被继承。

  • 用来定义一套基础框架和规范,强制子类必须实现某些方法(抽象方法)。

  • 可用来封装一些共通的逻辑,减少代码重复。

虚方法 (virtual):

  • 表示这个方法可以被子类重写(override)

  • 默认给了一套实现,你可以用,也可以替换掉

  • 避免了子类必须每次都写重复代码(子类用基类实现就好)

总结:

抽象类 + 虚方法组合使用的好处是:

  • 提供一个统一的接口和逻辑框架

  • 允许子类在不破坏主结构的情况下实现个性化逻辑(比如加缓存、记录日志)

🔗 组合使用的优势

抽象类 + 虚方法
✅ 定义统一规范和基础结构
✅ 提供默认逻辑(虚方法)
✅ 允许子类按需定制(重写虚方法)
✅ 提高代码复用性、可维护性
✅ 非侵入式扩展逻辑(如:记录日志、缓存等)

 🔧 举个实际应用场景(例如仓储):

public abstract class BaseRepository<T>
{public virtual void Add(T entity){// 默认实现:记录日志 + 保存Console.WriteLine("添加前记录日志");Save(entity);}protected abstract void Save(T entity); // 强制子类必须实现
}
public class UserRepository : BaseRepository<User>
{protected override void Save(User entity){// 实现具体的保存逻辑Console.WriteLine("保存用户到数据库");}public override void Add(User entity){// 也可以选择重写 Add,增加缓存逻辑等base.Add(entity);Console.WriteLine("添加用户成功");}
}

✅ 示例代码:调用 UserRepository

public class Program
{public static void Main(string[] args){var userRepo = new UserRepository();var newUser = new User { Id = 1, Name = "张三" };userRepo.Add(newUser);/* 日志打印结果添加前记录日志保存用户到数据库添加用户成功*/}
}// 假设 User 类如下:
public class User
{public int Id { get; set; }public string Name { get; set; }
}

🎯 实战目标

构建一个 基于接口 + 抽象类 + 泛型 的通用仓储:

  • 支持常规操作(增删改查)

  • 支持扩展方法(如分页、条件查询)

  • 易于继承 & 复用


🧩 步骤一:定义接口 IRepository<T>

public interface IRepository<T> where T : class
{Task<T> GetByIdAsync(int id);Task<IEnumerable<T>> GetAllAsync();Task AddAsync(T entity);void Update(T entity);void Delete(T entity);
}

🧱 步骤二:实现抽象类 BaseRepository<T>

以 EF Core 为例,注入 DbContext

public abstract class BaseRepository<T> : IRepository<T> where T : class
{protected readonly DbContext _context;protected readonly DbSet<T> _dbSet;public BaseRepository(DbContext context){_context = context;_dbSet = _context.Set<T>();}public virtual async Task<T> GetByIdAsync(int id){return await _dbSet.FindAsync(id);}public virtual async Task<IEnumerable<T>> GetAllAsync(){return await _dbSet.ToListAsync();}public virtual async Task AddAsync(T entity){await _dbSet.AddAsync(entity);}public virtual void Update(T entity){_dbSet.Update(entity);}public virtual void Delete(T entity){_dbSet.Remove(entity);}
}

🧪 步骤三:创建具体仓储类 UserRepository

public class UserRepository : BaseRepository<User>
{public UserRepository(MyDbContext context) : base(context){}// 可扩展自定义方法public async Task<User?> GetByEmailAsync(string email){return await _dbSet.FirstOrDefaultAsync(u => u.Email == email);}
}

🧩 步骤四:在服务中使用

public class UserService
{private readonly UserRepository _userRepo;public UserService(UserRepository userRepo){_userRepo = userRepo;}public async Task RegisterUser(User user){await _userRepo.AddAsync(user);// 保存到数据库由 UnitOfWork 或 DbContext 控制}
}

✅ 什么时候用接口 vs 抽象类?

特性接口(interface)抽象类(abstract class)
目的定义行为规范定义基本结构和部分实现
支持多继承✅ 支持❌ 不支持
可包含字段❌ 不行✅ 可以
可有构造函数❌ 不行✅ 可以
成员默认类型抽象(abstract)可以是抽象,也可以有默认实现
是否可实例化❌ 不行❌ 不行

仅供学习参考,

相关文章:

C#抽象类和虚方法的作用是什么?

抽象类 (abstract class)&#xff1a; 不能直接实例化&#xff0c;只能被继承。 用来定义一套基础框架和规范&#xff0c;强制子类必须实现某些方法&#xff08;抽象方法&#xff09;。 可用来封装一些共通的逻辑&#xff0c;减少代码重复。 虚方法 (virtual)&#xff1a; …...

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息 输出示例模块示例 输出示例 获取信息&#xff1a;WindowsFormsApp1.Form1.button1_Click(System.Object sender,System.EventArgs e) 引发的异常:“System.IndexOutOfRangeException”(位于 WindowsFormsApp1.ex…...

Apache SeaTunnel:新一代开源、高性能数据集成工具

Apache SeaTunnel 是一款开源、分布式、高性能的数据集成工具&#xff0c;可以通过配置快速搭建数据管道&#xff0c;支持实时海量数据同步。 Apache SeaTunnel 专注于数据集成和数据同步&#xff0c;主要旨在解决数据集成领域的常见问题&#xff1a; 数据源多样性&#xff1a…...

python+selenium+pytest自动化测试chrome driver版本下载

chrome浏览器chromedriver版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/#stable...

3.1 WPF使用MaterialDesign的介绍1

MaterialDesignInXAML Toolkit 是一个流行的开源 C# WPF 控件库,它实现了 Google 的 Material Design 规范,让开发者可以轻松创建现代化的 WPF 应用程序界面 Material Design 是一个流行的设计语言,由 Google 开发,旨在帮助开发者构建美观且一致的 UI 界面。对于使用 C# 的…...

从 0 到 1 打通 AI 工作流:Dify+Zapier 实现工具自动化调用实战

一、引言&#xff1a;当 AI 遇到工具孤岛 在企业数字化转型的浪潮中&#xff0c;AI 工具的应用早已从单一的对话交互进阶到复杂的业务流程自动化。但开发者常常面临这样的困境&#xff1a;本地开发的 MCP 工具&#xff08;如 ERP 数据清洗脚本、CRM 工单系统 API&#xff09;如…...

【算法笔记】如何优雅的进行字符串操作

最近的CCCC天梯赛又出了非常恶心的字符串题~ 在编程竞赛&#xff08;特别是CCCC天梯赛&#xff09;中&#xff0c;字符串操作类题目往往看似简单却暗藏陷阱。本文将以Python、Java、C 三剑客为例&#xff0c;总结高频字符串操作的优雅实现方案&#xff0c;助你快速攻克字符串类…...

docker转移镜像

1、场景 有网络环境向无网络环境转移镜像。无法拉取的镜像&#xff08;外网无法访问&#xff09;下载镜像转移到服务器上。 2、docker转移 2.1 镜像服务器 保存镜像 列出项目使用的所有镜像 docker images 保存所有镜像为 tar 文件 保存docker镜像 docker save -o my_…...

【Rust 精进之路之第12篇-生命周期·入门】为何需要与显式标注 (`‘a`):让编译器读懂引用的“有效期”

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:悬垂引用的“幽灵”与编译器的“侦探” 在前面的章节中,我们深入学习了 Rust 的所有权系统,以及如何通过引用 (& 和 &mut) 进行借用,从而在不转移所有权的情况下安…...

Vue.js 之 `v-for` 命令详解

Vue.js 之 v-for 命令详解 在 Vue.js 中&#xff0c;v-for 是一个非常强大的指令&#xff0c;用于遍历数组或对象中的数据&#xff0c;并渲染相应的 DOM 元素。无论是在列表展示、表单生成还是动态组件加载中&#xff0c;v-for 都发挥着重要作用。本文将详细介绍 v-for 的用法…...

Spring Boot中`logging.config`配置项的详解及使用说明

以下是Spring Boot中logging.config配置项的详解及使用说明&#xff1a; 1. logging.config 作用 功能&#xff1a;指定自定义日志配置文件的路径&#xff0c;覆盖Spring Boot默认的日志配置。适用场景&#xff1a;当需要深度定制日志行为&#xff08;如输出格式、文件路径、…...

相机模型--CMOS和CCD的区别

1--CMOS和CCD的工作原理 CCD&#xff08;Charge Coupled Device&#xff0c;电荷耦合器件&#xff09;&#xff1a; 1. 图像通过光电效应在感光单元中转化为电荷&#xff1b; 2. 每个像素上的电荷被依次“耦合”并传输到芯片的角落&#xff0c;通过一个或几个模拟输出放大器输…...

el-date-picker时间范围 赋值报错问题

问题&#xff1a; 点击时间范围组件右边清除图标&#xff0c;点击近6小时会把设置好的时间赋值给时间范围组件 但是出现报错 原因&#xff1a; 尝试对null值进行属性设置操作&#xff1a;修改一个数组的元素&#xff0c;但此时这个数组是null&#xff0c;而不是预期的数组类型…...

为啥低速MCU单板辐射测试会有200M-1Ghz的辐射信号

低速MCU&#xff08;如8位或16位单片机&#xff09;单板在辐射测试中出现 200MHz~1GHz的高频辐射信号&#xff0c;看似不合理&#xff0c;但实际上是由多种因素共同导致的。以下是详细原因分析及解决方案&#xff1a; 1.根本原因分析: (1) 时钟谐波与开关噪声 低速MCU的时钟谐…...

【音视频】FFmpeg解封装

解封装 复用器&#xff0c;比如MP4/FLV 解复用器&#xff0c;MP4/FLV 封装格式相关函数 avformat_alloc_context(); 负责申请一个AVFormatContext结构的内存,并进行简单初始化avformat_free_context(); 释放该结构里的所有东西以及该结构本身avformat_close_input();关闭解复…...

使用VHDL语言实现TXT文件的读写操作

使用FPGA进行图像处理时&#xff0c;通常需要将TXT文件中的图像数据读出到TestBench中&#xff0c;并将仿真的结果写入到TXT文件中&#xff0c;用于确认图像处理的结果是否正确。 VHDL中TXT文件的读写操作如下所示&#xff0c; --------------------------------------------…...

OpenLDAP 管理 ELK 用户

文章目录 一、新建 ELK 相关用户组二、配置 Elasticsearch2.1 修改 elasticsearch.yml 配置2.2 使用 API 接口建立角色和用户映射 三、Kibana 验证用户登录 一、新建 ELK 相关用户组 由于后续要将 LDAP 的用户与 ELK 的角色进行映射&#xff0c;所以需先创建几个以 ELK 的角色…...

第十七届“华中杯”大学生数学建模挑战赛题目A题 晶硅片产销策略优化 完整成品 代码 模型 思路 分享

近年来&#xff0c;高纯度晶硅片需求的增长引发了更激烈的市场竞争。晶硅片企业需要在成本控制、利润优化和供需管理之间取得平衡&#xff0c;以提高经营效率和市场竞争力。晶硅片的生产是一个高能耗、高成本的过程&#xff0c;企业效益会受到原材料价格波动、市场需求变化以及…...

iOS 中的虚拟内存 (理解为什么需要虚拟内存)

什么叫“虚拟地址空间”&#xff1f; 一句话&#xff1a;它是 CPU 看得见、App 以为自己独享&#xff0c;但实际上会被内核和硬件&#xff08;MMU&#xff09;动态翻译到真实 物理内存 的一整块“虚拟地图”。 1. 背景&#xff1a;为什么要“虚拟”&#xff1f; 需求虚拟地址空…...

网络层理解

网络层理解 网络层是 OSI 模型的第三层&#xff0c;主要负责 跨网络的数据传输&#xff0c;核心任务是 路由选择 和 分组转发。 网络层核心功能 网络层关键协议 协议作用示例IP (IPv4/IPv6)数据包路由和寻址192.168.1.1ICMP网络状态检测和错误报告ping、tracerouteOSPF/BGP动…...

代码随想录训练营38天 || 322. 零钱兑换 279. 完全平方数 139. 单词拆分

322. 零钱兑换 思路&#xff1a; 动规5部曲&#xff1a; 1.确定dp数组以及下标的含义&#xff1a; dp数组表示能凑出零钱的最少硬币数&#xff0c;下标表示要兑换的零钱 2.确定递推公式&#xff1a; j为背包容量&#xff0c;i为物品的下标 dp[ j ] min(dp[ j -coins[ i…...

从Archery到NineData:积加科技驱动数据库研发效能与数据安全双升级

积加科技作为国内领先的企业级数字化解决方案服务商&#xff0c;依托自研的 A4X 数字化平台&#xff08;https://a4x.io/&#xff09;&#xff0c;专注于为全球范围内的视觉物联网&#xff08;IoT&#xff09;设备提供 PaaS/SaaS 服务。致力于运用 AI 技术赋能物联网世界的各类…...

C#委托介绍

委托可以将方法作为参数传递&#xff0c;同时委托也可以自己作为参数传递 委托可分为自定义委托delegate 无返回值的Action 与有返回值的Func委托 也有匿名委托与Lamada 委托支持多播是事件的基础 用处如在分线程调用主线程的UI invoke public delegate string Say(stri…...

解决splice改变原数组的BUG(拷贝数据)

项目场景&#xff1a; 项目中难免遇到需要删除改变数组的方法&#xff0c;去重&#xff0c;删除不要的数据等 问题描述&#xff1a; 但是splice方法会删除掉数据改变原数组&#xff0c;返回的是改变之后的数组&#xff0c;即使你是赋值的还是会影响到原数组的数据 GoodsInfo…...

齐次坐标系下的变换矩阵

理解齐次坐标系下的变换矩阵 文章目录 理解齐次坐标系下的变换矩阵1 引言2 齐次坐标系的简要介绍2.1 齐次坐标系的定义2.2 为什么需要齐次坐标系&#xff1f;2.3 齐次坐标系的特殊性质2.3.1 点和向量的区分2.3.2 投影变换 3 齐次坐标系下的变换矩阵3.1 二维变换矩阵平移变换缩放…...

开源Midjourney替代方案:企业级AI绘画+PPT生成系统+AI源码

「AI取代设计师&#xff1f;」开源Midjourney替代方案&#xff1a;企业级AI绘画PPT生成系统 ——零代码私有化部署&#xff0c;5倍速出图100%版权合规 设计师行业的危机与机遇 1. 传统设计流程的致命短板 痛点 人工设计 AI系统 单张海报耗时 3小时&#xff08;含反复修改…...

2025.04.20【Lollipop】| Lollipop图绘制命令简介

Customize markers See the different options allowing to customize the marker on top of the stem. Customize stems See the different options allowing to customize the stems. 文章目录 Customize markersCustomize stems Lollipop图简介R语言中的Lollipop图使用ggp…...

【Harmony】常用工具类封装

文章目录 一&#xff0c;简介二&#xff0c;网络请求工具类2.1、鸿蒙原生http封装2.2、第三方axios封装(需提前下载依赖) 三、录音笔相关工具类3.1、录音封装(录入)3.2、录音封装(放音/渲染)3.3、文件写入封装(针对录音/放音功能) 四、RDB关系型数据库4.1、relationalStore简答…...

DCDC芯片,boost升压电路设计,MT3608 芯片深度解析:从架构到设计的全维度技术手册

一、硬件架构解析:电流模式升压 converter 的核心设计 (一)电路拓扑与核心组件 MT3608 采用恒定频率峰值电流模式升压(Boost)转换器架构,核心由以下模块构成: 集成功率 MOSFET 内置 80mΩ 导通电阻的 N 沟道 MOSFET,漏极(Drain)对应引脚 SW,源极(Source)内部接…...

Cline 之Plan和Act模式

Cline 提供了 "Plan & Act"双模式开发框架。适用在不同的场景。 一、核心模式理念 通过结构化开发流程提升AI编程效率&#xff0c;采用"先规划后执行"的核心理念。 该框架旨在帮助开发者构建更易维护、准确性更高的代码&#xff0c;同时显著缩短开发…...