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

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)&#xff0c…...

网络安全-等级保护(等保) 0. 前言

各位伙伴好: 招投标总结已过去一年了,时间飞逝,一直忙于工作,等保相关的内容断断续续整理了近半年的时间,但一直无暇完成博客内容。 等保已经是一个成熟的体系,现在已进入等保2.0时代,相关政策…...

【数据结构】树的介绍

目录 一、树1.1什么是树?1.2 树的概念与结构1.3树的相关术语1.4 树形结构实际运用场景 二、二叉树2.1 概念与结构2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 个人主页,点击这里~ 数据结构专栏,点击这里~ 一、树 1.1什么是树&#xff1…...

大模型是如何把向量解码成文字输出的

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 渲染-区域纹理图添加

引入-初始化地图&#xff08;关键代码&#xff09; // 初始化页面引入高德 webapi -- index.html 文件 <script src https://webapi.amap.com/maps?v2.0&key您申请的key值></script>// 添加地图容器 <div idcontainer ></div>// 地图初始化应该…...

K8S核心技术点

Pod&#xff0c;Service和Deployment的关系 Pod&#xff1a;Kubernetes 中最小的部署单元&#xff0c;用于运行容器化应用。 Service&#xff1a;提供服务发现和负载均衡&#xff0c;为 Pod 提供稳定的网络端点&#xff0c;ClusterIP&#xff0c;NodePort&#xff0c;LoadBala…...

Spring Boot 与 TDengine 的深度集成实践(二)

创建数据模型 定义实体类 在完成数据库连接配置后&#xff0c;我们需要创建与 TDengine 表对应的 Java 实体类。实体类是 Java 对象与数据库表之间的映射&#xff0c;通过定义实体类&#xff0c;我们可以方便地在 Java 代码中操作数据库中的数据&#xff0c;实现数据的持久化…...

搭建hadoop集群模式并运行

3.1 Hadoop的运行模式 先去官方看一看Apache Hadoop 3.3.6 – Hadoop: Setting up a Single Node Cluster. 本地模式&#xff1a;数据直接存放在Linux的磁盘上&#xff0c;测试时偶尔用一下 伪分布式&#xff1a;数据存放在HDFS&#xff0c;公司资金不足的时候用 完全分布式&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学生成绩管理系统

前言 该系统为学生成绩管理系统&#xff0c;可以当作学习参考&#xff0c;也可以成为Spirng Boot初学者的学习代码&#xff01; 系统描述 学生成绩管理系统提供了三种角色&#xff1a;学生&#xff0c;老师&#xff0c;网站管理员。主要实现的功能如下&#xff1a; 登录 &a…...

马井堂js设置倒计时页面

js-倒计时页面 提示&#xff1a;这里简述项目相关背景&#xff1a; 例如&#xff1a;项目场景&#xff1a;倒计时需求 <!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 生态系统&#xff01;此次集成确保了 SGLang 符合 PyTorch 的技术标准与最佳实践&#xff0c;为开发者提供了一个可靠且社区支持的框架&#xff0c;助力大规模语言模型&#xff08;LLM&#xff09;实现高效且灵活的推理。 如需深入了解 PyTorch…...

时序数据库 TDengine Cloud 私有连接实战指南:4步实现数据安全传输与成本优化

小T导读&#xff1a;在物联网和工业互联网场景下&#xff0c;企业对高并发、低延迟的数据处理需求愈发迫切。本文将带你深入了解 TDengineCloud 如何通过全托管服务与私有连接&#xff0c;帮助企业实现更安全、更高效、更低成本的数据采集与传输&#xff0c;从架构解析到实际配…...