C#核心学习(八)面向对象--封装(7)终章 C#内部类和分部类、密封类
目录
一、内部类(Inner Class)
1. 什么是内部类?
2. 内部类的作用
3. 如何定义内部类?
4. 常见应用场景
二、分部类(Partial Class)
1. 什么是分部类?
2. 分部类的写法
3. 分部方法(Partial Methods)
三、内部类 vs 分部类
四、总结与注意事项
1. 内部类的使用技巧
2. 分部类的使用技巧
3. 注意事项
补充一个小知识:密封类:
1.什么是密封类? 用 sealed 关键字修饰的类,表示禁止其他类继承它,是类继承链的终点。
2.密封类的作用
3.如何定义密封类?
4.常见应用场景
5.注意事项
6.密封方法(扩展知识) 在非密封类中,可用 sealed 关键字标记重写方法,禁止子类再次覆盖:
在C#开发中,你是否为代码臃肿、逻辑外泄或意外继承而头疼?内部类将关联逻辑嵌套封装,分部类拆解巨型代码文件,密封类则终结不受控的继承链——三者如同封装设计的“三叉戟”,分别解决代码组织、维护复杂度与安全性问题。本文将用真实案例解析它们的核心价值,助你写出更简洁、安全且易维护的代码。
一、内部类(Inner Class)
1. 什么是内部类?
内部类(嵌套类)是定义在另一个类或结构体内部的类。其主要目的是逻辑分组和封装细节。
- 访问权限特点:
- 默认访问修饰符为
private,可显式指定为public/protected/internal。 - 可访问外部类的私有成员(包括字段、方法)。
- 默认访问修饰符为
2. 内部类的作用
- 隐藏实现细节:将辅助类(如迭代器、状态机)隐藏在外部类内部。
- 逻辑聚合:将与外部类紧密相关的类组织在一起。
- 访问控制:限制内部类仅在外部类范围内使用。
3. 如何定义内部类?
public class OuterClass
{private string _secret = "Confidential";// 内部类private class InnerClass {public void Print(OuterClass outer) {// 访问外部类的私有字段Console.WriteLine(outer._secret);}}public void UseInnerClass() {// 创建内部类实例InnerClass inner = new InnerClass();inner.Print(this);}
}// 使用示例
OuterClass outer = new OuterClass();
outer.UseInnerClass(); // 输出 "Confidential"
4. 常见应用场景
- 迭代器模式:封装集合的遍历逻辑。
- Builder模式:隐藏复杂对象的构造过程。
- 状态管理:在有限状态机中定义状态类。
二、分部类(Partial Class)
1. 什么是分部类?
分部类(partial class)允许将一个类拆分到多个文件中定义,编译器会合并处理。
- 核心用途:
- 分离自动生成代码与手动编写代码(如ASP.NET Web Forms、WinForms设计器文件)。
- 大型类的模块化管理。
2. 分部类的写法
// File1.cs
public partial class DataProcessor
{public void LoadData() {// 数据加载逻辑}
}// File2.cs
public partial class DataProcessor
{public void ProcessData() {// 数据处理逻辑}
}// 编译器合并后的等效代码:
public class DataProcessor
{public void LoadData() { ... }public void ProcessData() { ... }
}
3. 分部方法(Partial Methods)
- 定义在分部类中的方法,可分离声明与实现。
- 规则:
- 必须为
partial void方法。 - 若未实现,编译器会移除声明。
- 必须为
// File1.cs
public partial class Logger
{// 声明分部方法partial void LogStart();public void Start() {LogStart(); // 若未实现,此行代码会被移除}
}// File2.cs
public partial class Logger
{// 实现分部方法partial void LogStart() {Console.WriteLine("Logging started.");}
}
三、内部类 vs 分部类
| 特性 | 内部类(嵌套类) | 分部类(Partial Class) |
|---|---|---|
| 核心目的 | 逻辑分组与封装细节 | 拆分代码到多个文件 |
| 文件组织 | 同一文件中定义 | 跨多个文件定义 |
| 访问权限 | 可访问外部类私有成员 | 同普通类(无特殊权限) |
| 典型场景 | 迭代器、状态类 | 代码生成工具、大型类模块化管理 |
四、总结与注意事项
1. 内部类的使用技巧
- 访问控制:优先设为
private,仅在需要时开放访问。 - 避免滥用:过度嵌套会导致代码可读性下降。
- 应用场景:适合封装与外部类强相关的辅助逻辑。
2. 分部类的使用技巧
- 代码生成友好性:分离工具生成的代码(如Entity Framework实体类)。
- 团队协作:多人协作时可按功能模块拆分文件。
- 分部方法限制:仅支持
void返回类型且不能为public。
3. 注意事项
- 内部类的序列化:嵌套类可能增加序列化复杂度。
- 分部类的命名空间:所有分部类必须在同一命名空间。
- 代码导航:分部类可能增加IDE中代码跳转的复杂度。
结语:通过内部类隐藏复杂逻辑,利用分部类拆分代码文件,C#的封装特性让代码更加模块化、易维护。保持代码简洁,避免过度设计,是高效开发的关键!我目前还没有什么应用过的场景,目前来说我们不必了解太多,等到学到框架的时候,可以继续深入。
补充一个小知识:密封类:
这个知识点,大家可以在后面看了继承以后再来观看会有更深的体会,因为在继承中,有的时候,会为了保护最底层不被继续继承后随意修改,所以使用关键字进行密封禁止其他的类继承。
1.什么是密封类?
用 sealed 关键字修饰的类,表示禁止其他类继承它,是类继承链的终点。
public sealed class Logger
{public void Log(string message) {Console.WriteLine(message);}
}// 编译错误:无法继承密封类
public class FileLogger : Logger { }
2.密封类的作用
- 防止派生:保护核心类逻辑,避免被意外继承或篡改(如系统类
String是密封的)。 - 性能优化:帮助编译器内联方法调用(减少虚方法表开销)。
- 框架设计:明确限制用户扩展点(如某些设计模式中的最终组件)。
3.如何定义密封类?
使用关键字 sealed
public sealed class SecurityToken
{private byte[] _encryptedData;public void Decrypt(string key) {// 核心解密逻辑(禁止外部覆盖)}
}
注意!!!!
- 可继承其他类:密封类自身可以继承其他非密封类。
- 不可被继承:任何尝试继承的操作都会导致编译错误。
4.常见应用场景
- 工具类:提供静态方法且无需扩展(如
Math类)。 - 敏感操作类:加密、授权等需要保护完整性的逻辑。
- 性能关键代码:高频调用的基础类型(如游戏引擎中的向量计算类)。
- 框架约束:明确禁止用户自定义子类(如ASP.NET中的某些管道组件)。
5.注意事项
- 慎用密封:过度使用会限制代码扩展性,需权衡灵活性和安全性。
- 配合静态类:若类完全无需实例化,可改用
static class(隐式密封)。 - 单元测试:密封类可能增加Mock测试难度,可通过接口解耦。
- 性能权衡:现代编译器优化能力较强,除非实测有收益,否则不必仅为性能而密封
6.密封方法(扩展知识)
在非密封类中,可用 sealed 关键字标记重写方法,禁止子类再次覆盖:
public class Device
{public virtual void Initialize() { }
}public class Printer : Device
{// 子类重写并密封该方法public sealed override void Initialize() {// 打印机专用初始化}
}public class LaserPrinter : Printer
{// 编译错误:无法覆盖密封方法public override void Initialize() { }
}
结语:密封类作为继承链的"终结者",在保护核心逻辑和性能优化中扮演关键角色。结合框架设计与实际需求,合理使用能让代码更健壮、更高效!
相关文章:
C#核心学习(八)面向对象--封装(7)终章 C#内部类和分部类、密封类
目录 一、内部类(Inner Class) 1. 什么是内部类? 2. 内部类的作用 3. 如何定义内部类? 4. 常见应用场景 二、分部类(Partial Class) 1. 什么是分部类? 2. 分部类的写法 3.…...
[ctfshow web入门] web25
信息收集 要想拿到flag,需要突破两层if。 解题 第一个if 传入r0,拿到mt_rand的值,由于每一次访问都会重新设置种子,所以每一次访问都是一样的随机数。 所以我们的r mt_rand-显示的值 1799250188 r1799250188就可以突破第一…...
局域网访问 Redis 方法
局域网访问 Redis 方法 默认情况下,Redis 只允许本机 (127.0.0.1) 访问。如果你想让局域网中的其他设备访问 Redis,需要 修改 Redis 配置,并确保 防火墙放行端口。 方法 1:修改 Redis 配置 1. 修改 redis.conf(或 me…...
oracle 索引失效
在 Oracle 11g 中,索引失效的常见原因包括函数修改列、隐式类型转换、统计信息过时等,解决方法需结合版本特性(如虚拟列、索引跳跃扫描)。通过执行计划分析、统计信息维护和合理使用提示(Hints),…...
网络安全-等级保护(等保) 0. 前言
各位伙伴好: 招投标总结已过去一年了,时间飞逝,一直忙于工作,等保相关的内容断断续续整理了近半年的时间,但一直无暇完成博客内容。 等保已经是一个成熟的体系,现在已进入等保2.0时代,相关政策…...
【数据结构】树的介绍
目录 一、树1.1什么是树?1.2 树的概念与结构1.3树的相关术语1.4 树形结构实际运用场景 二、二叉树2.1 概念与结构2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 个人主页,点击这里~ 数据结构专栏,点击这里~ 一、树 1.1什么是树࿱…...
大模型是如何把向量解码成文字输出的
hidden state 向量 当我们把一句话输入模型后,例如 “Hello world”: token IDs: [15496, 995]经过 Embedding Transformer 层后,会得到每个 token 的中间表示,形状为: hidden_states: (batch_size, seq_len, hidd…...
Android源码之App启动
目录 App启动概述 App启动过程 App启动过程图 源码概述 跨进程启动 进程内启动 下面以应用桌面Launcher启动App的MainActivity来举例: App启动概述 首先,MainActivity是由Launcher组件来启动的,而Launcher又是通过Activity管理服务Act…...
nginx如何实现负载均衡?
Nginx 是一款高性能的 Web 服务器和反向代理服务器,它可以通过配置实现负载均衡功能。以下是实现负载均衡的详细步骤和方法: 1. 基本概念 负载均衡是将客户端请求分发到多个后端服务器上,以提高系统的可用性和性能。Nginx 支持多种负载均衡策…...
【GESP】C++二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S
GESP二级练习,多层循环分支练习,难度★✮☆☆☆。 题目题解详见:https://www.coderli.com/gesp-2-luogu-b3721/ 【GESP】C二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S | OneCoderGESP二级练习,多层循环分支练习&am…...
2. Qt界面文件原理
本节主要介绍ui文件如何与窗口关联,并通过隐式连接方式显示对话框 本文部分ppt、视频截图原链接:[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1 UI文件如何与窗口关联 1.1 mainwindow.cpp的头文件ui_mainwindow.h 根据编译原理的基本规…...
Elastic 的 OpenTelemetry 分发版(EDOT)现已正式发布:开源、可用于生产环境的 OTel
作者:来自 Elastic Miguel Luna 及 Bahubali Shetti Elastic 自豪地宣布正式发布 Elastic OpenTelemetry 分发版(Elastic Distributions of OpenTelemetry - EDOT),其中包含 Elastic 自定义版本的 OpenTelemetry Collector 以及多…...
docker部署jenkins并成功自动化部署微服务
一、环境版本清单: docker 26.1.4JDK 17.0.28Mysql 8.0.27Redis 6.0.5nacos 2.5.1maven 3.8.8jenkins 2.492.2 二、服务架构:有gateway,archives,system这三个服务 三、部署步骤 四、安装linux 五、在linux上安装redis&#…...
UML对象图
UML对象图 一、对象图核心概念 对象图(Object Diagram)描述的是系统在某一时刻对象(实例)的状态快照。它关注的是实际对象之间的实例关系,而不是类与类之间的静态结构。主要特点有: 对象(Ob…...
【NLP 53、投机采样加速推理】
目录 一、投机采样 二、投机采样改进:美杜莎模型 流程 改进 三、Deepseek的投机采样 流程 Ⅰ、输入文本预处理 Ⅱ、引导模型预测 Ⅲ、候选集筛选(可选) Ⅳ、主模型验证 Ⅴ、生成输出与循环 骗你的,其实我在意透了 —— 25.4.4 一、…...
[250403] HuggingFace 新增检查模型与电脑兼容性的功能 | Firefox 发布137.0 支持标签组
目录 Hugging Face 让寻找兼容的 AI 模型变得更容易Firefox 137 版本更新摘要 Hugging Face 让寻找兼容的 AI 模型变得更容易 Hugging Face 是一个流行的在线平台,用于访问开源人工智能 (AI) 工具和模型。该平台推出了一项有用的新功能,允许个人轻松检查…...
VScode连接CentOS 7.6虚拟机
本文内容:在Windows上使用VMware运行虚拟机,然后使用VScode连接CentOS 7.6虚拟机。 进入系统前 安装VMware 安装教程参考:VMware安装 下载CentOS 7.6镜像 可以使用国内镜像源,但是一般国内镜像源要么已经不维护CentOS 7.6这个…...
Android Hilt 教程
Android Hilt 教程 —— 一看就懂,一学就会 1. 什么是 Hilt?为什么要用 Hilt? Hilt 是 Android 官方推荐的 依赖注入(DI)框架,基于 Dagger 开发,能够大大简化依赖注入的使用。 为什么要用 Hi…...
高德地图 3D 渲染-区域纹理图添加
引入-初始化地图(关键代码) // 初始化页面引入高德 webapi -- index.html 文件 <script src https://webapi.amap.com/maps?v2.0&key您申请的key值></script>// 添加地图容器 <div idcontainer ></div>// 地图初始化应该…...
K8S核心技术点
Pod,Service和Deployment的关系 Pod:Kubernetes 中最小的部署单元,用于运行容器化应用。 Service:提供服务发现和负载均衡,为 Pod 提供稳定的网络端点,ClusterIP,NodePort,LoadBala…...
Spring Boot 与 TDengine 的深度集成实践(二)
创建数据模型 定义实体类 在完成数据库连接配置后,我们需要创建与 TDengine 表对应的 Java 实体类。实体类是 Java 对象与数据库表之间的映射,通过定义实体类,我们可以方便地在 Java 代码中操作数据库中的数据,实现数据的持久化…...
搭建hadoop集群模式并运行
3.1 Hadoop的运行模式 先去官方看一看Apache Hadoop 3.3.6 – Hadoop: Setting up a Single Node Cluster. 本地模式:数据直接存放在Linux的磁盘上,测试时偶尔用一下 伪分布式:数据存放在HDFS,公司资金不足的时候用 完全分布式&a…...
Qt实现鼠标右键弹出弹窗退出
Qt鼠标右键弹出弹窗退出 1、鼠标右键实现1.1 重写鼠标点击事件1.2 添加头文件1.3 添加定义2、添加菜单2.1添加菜单头文件2.2创建菜单对象2.3 显示菜单 3、添加动作3.1添加动作资源文件3.2 添加头文件3.3 创建退出动作对象3.4菜单添加动作对象 4、在当前鼠标位置显示菜单4.1当前…...
Spring 服务调用接口时,提示You should be redirected automatically to target URL:
问题 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>Redirecting...</title><h1>Redirecting...</h1><p>You should be redirected automatically to target URL: <a href"http://xxx/api/v1/branch…...
Springboot整合Mybatis+Maven+Thymeleaf学生成绩管理系统
前言 该系统为学生成绩管理系统,可以当作学习参考,也可以成为Spirng Boot初学者的学习代码! 系统描述 学生成绩管理系统提供了三种角色:学生,老师,网站管理员。主要实现的功能如下: 登录 &a…...
马井堂js设置倒计时页面
js-倒计时页面 提示:这里简述项目相关背景: 例如:项目场景:倒计时需求 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&…...
C#里第一个WPF程序
WPF程序对界面进行优化,但是比WINFORMS的程序要复杂很多, 并且界面UI基本上不适合拖放,所以需要比较多的时间来布局界面, 产且需要开发人员编写更多的代码。 即使如此,在面对诱人的界面表现, 随着客户对界面的需求提高,还是需要采用这样的方式来实现。 界面的样式采…...
【Java设计模式】第5章 工厂方法模式讲解
5. 工厂方法模式 5.1 工厂方法讲解 定义:定义一个创建对象的接口,由子类决定实例化的类,将对象创建延迟到子类。适用场景: 创建对象需要大量重复代码。客户端不依赖具体产品的创建细节。优点: 符合开闭原则,新增产品只需扩展子类。客户端仅依赖抽象接口,不依赖具体实现…...
PyTorch 生态迎来新成员:SGLang 高效推理引擎解析
SGLang 现已正式融入 PyTorch 生态系统!此次集成确保了 SGLang 符合 PyTorch 的技术标准与最佳实践,为开发者提供了一个可靠且社区支持的框架,助力大规模语言模型(LLM)实现高效且灵活的推理。 如需深入了解 PyTorch…...
时序数据库 TDengine Cloud 私有连接实战指南:4步实现数据安全传输与成本优化
小T导读:在物联网和工业互联网场景下,企业对高并发、低延迟的数据处理需求愈发迫切。本文将带你深入了解 TDengineCloud 如何通过全托管服务与私有连接,帮助企业实现更安全、更高效、更低成本的数据采集与传输,从架构解析到实际配…...
