13-C#

cadence数模混合仿真反标sdf 数模混合IC设计时经常要调用一些Verilog模块(最简单的例如SPI接口),在前仿时一般直接用rtl代码来仿真,但是后仿时要关注因寄生带来的延迟,避免这些额外的延迟导致时序错误,因此不能简单地采用RTL来仿真。 一般有两种办法:1是采用由RTL综合得到的门级电路来仿真,这种方法比较简单,但是缺点是规模较大,而且只包括门延迟不包括因版图导致的线延迟;如果想要仿真更精细,就要对该这部分门电路提取寄生参数; 另一种方式是利用sdf文件(standard delay format)来进行仿真。后端工具在布局布 阅读详情

C#.Net-设计模式六大原则-学习笔记

六大原则是写出高质量、可维护代码的基础,记住一句话:对修改关闭,对扩展开放是核心思想,其余五条都是在不同角度强化这个目标。


一、SRP — 单一职责原则

Single Responsibility Principle

核心思想

一个类(或方法)只负责一件事,只有一个引起它变化的原因。

通俗理解

厨师只管做菜,服务员只管上菜,收银员只管收钱。如果一个人全干,哪个环节出问题都要改这个人。

代码中的问题演示

// 反例:Animal 类的 Breath() 方法承担了所有动物的呼吸逻辑
public void Breath()
{
    if (_Name.Equals("鸡")) Console.WriteLine("呼吸空气");
    else if (_Name.Equals("鱼")) Console.WriteLine("呼吸水");
    // 每新增一种动物就要改这个方法 —— 违反SRP
}

正确做法:拆分成多个类

// 抽象基类定义职责
public abstract class AbstractAnimal
{
    protected string _Name;
    public abstract void Breath();  // 呼吸是谁的职责?各自子类的
    public abstract void Action();  // 行动是谁的职责?各自子类的
}

public class Chicken : AbstractAnimal
{
    public override void Breath() => Console.WriteLine($"{_Name} 呼吸空气");
    public override void Action() => Console.WriteLine($"{_Name} flying");
}

public class Fish : AbstractAnimal
{
    public override void Breath() => Console.WriteLine($"{_Name} 呼吸水");
    public override void Action() => Console.WriteLine($"{_Name} swimming");
}

实际案例:BankClient 拆分

以银行客户端为例,一个典型的违反 SRP 的写法是把所有逻辑堆在一个类里:

// 反例:所有职责混在一起
public class BankClient
{
    public void Run()
    {
        // 1. 验证用户
        // 2. 查询余额
        // 3. 计算利息
        // 4. 展示结果
        // 任何一个环节变化,都要改这个类
    }
}

正确做法是按变化原因拆分:

public class UserCheckService  { public bool CheckUser(string id) { ... } }
public class AccountService    { public decimal GetBalance(string id) { ... } }
public class InterestCalculator{ public decimal Calculate(decimal balance) { ... } }
public class DisplayService    { public void Show(decimal amount) { ... } }

验证逻辑可能从数据库换成远程接口,余额查询可能换数据源——变化原因不同,就该分开。

记忆口诀

一个类,一件事,改一处,不牵连。


二、OCP — 开闭原则

Open Closed Principle

核心思想

对扩展开放,对修改关闭。新增功能时,尽量不改已有代码,而是新增代码。

通俗理解

手机出了新功能,不是把旧手机拆了重装,而是出一款新型号。

四种扩展方式

以 Student.Study() 方法为例,当需要新增"免费学习"功能时,有四种做法,优劣各不同:

方式1:直接改原方法(最差)

public virtual void Study(bool isFree = false)
{
    if (isFree) Console.WriteLine("Study Free");
    else Console.WriteLine("Study Paid");
    // 改了原有逻辑,可能引入新 Bug,影响已有功能
}

方式2:在原类新增方法(次之)

public class Student
{
    public virtual void Study() => Console.WriteLine("Study Paid");
    public virtual void StudyFree() => Console.WriteLine("Study Free"); // 新增,不改原方法
}
// 缺点:原类仍然被修改,随着功能增多类会越来越臃肿

方式3:继承扩展(推荐)

public class StudentChild : Student
{
    public override void Study()
    {
        base.Study();
        Console.WriteLine("Study Review"); // 扩展行为
        // 完全不修改父类,通过继承扩展
    }
}

方式4:新增独立类(最彻底)

public class StudentFree  // 全新的类,完全不影响原有 Student
{
    public virtual void Study() => Console.WriteLine("Study Free");
}

记忆口诀

加功能,加代码;别动旧代码。


三、LSP — 里氏替换原则

Liskov Substitution Principle

核心思想

子类必须能够替换父类使用,且程序行为不变。换句话说:能用父类的地方,换成子类也没问题。

通俗理解

你叫了一辆出租车,来了一辆网约车,你还是能到达目的地——这就是替换。但如果来了一辆自行车,你就到不了——这就违反了替换原则。

C# 中的多态机制

理解 LSP 的关键是搞清楚 C# 里三种方法的行为差异:

// 父类引用指向子类对象
ParentClass instance = new ChildClass();

instance.CommonMethod();   // 调用的是父类的 CommonMethod(new 隐藏,不是多态)
instance.VirtualMethod();  // 调用的是子类的 VirtualMethod(override 覆写,多态生效)
instance.AbstractMethod(); // 调用的是子类的 AbstractMethod(抽象方法必须覆写)

三种方法的区别:

方法类型关键字子类能否覆写父类引用调用结果
普通方法无用 new 隐藏调用父类版本
虚方法virtual用 override调用子类版本(多态)
抽象方法abstract必须 override调用子类版本(多态)

什么时候不该继承?

继承要满足"is-a"关系。如果子类无法完整履行父类的所有契约,就不该继承。

以 People 和 Japanese 为例:假设 People 有一个 Traditional() 方法(传统礼仪),而 Japanese 的礼仪体系完全不同,强行继承后要么抛异常,要么调用方需要做类型判断——这就违反了 LSP。

// 违反LSP的写法
public class Japanese : People
{
    public override void Traditional()
    {
        throw new NotImplementedException(); // 被迫实现,但实际不支持
    }
}

// 正确:断掉不合适的继承关系,各自独立
public class Japanese
{
    public void Ninja() { ... }  // 只实现自己真正有的行为
}

判断是否该继承的简单方法: 把子类替换到所有使用父类的地方,程序行为是否仍然正确?如果不是,就不该继承。

记忆口诀

子类替父类,行为不能变;不是"是一种",就别乱继承。


四、ISP — 接口隔离原则

Interface Segregation Principle

核心思想

不要让一个类被迫实现它用不到的接口方法。接口要小而专,不要大而全。

通俗理解

你去餐厅只想点菜,不需要同时学会做菜、洗碗、收银。如果菜单上把这些都列出来要求你会,那就太荒谬了。

反例:大而全的接口

// 问题接口:包含了所有功能
public interface IExtendAll
{
    void Photo();   // 拍照
    void Online();  // 上网
    void Game();    // 游戏
    void Record();  // 录像
    void Movie();   // 看电影
    void Map();     // 地图
    void Pay();     // 支付
}

TV 类实现 IExtendAll 的问题:

public class TV : IExtendAll
{
    public void Online() { ... }  // 电视能上网 ✓
    public void Movie() { ... }   // 电视能看电影 ✓
    public void Photo() { throw new NotImplementedException(); }  // 电视不能拍照!被迫实现 ✗
    public void Pay()   { throw new NotImplementedException(); }  // 电视不能支付!被迫实现 ✗
}

正确做法:拆分成小接口

public interface IExtendPhoto  { void Photo(); }
public interface IExtendRecord { void Record(); }
public interface IExtendGame   { void Online(); void Game(); }

// 相机只实现它需要的接口
public class Camera : IExtendPhoto, IExtendRecord
{
    public void Photo()  { ... }
    public void Record() { ... }
    // 不需要实现 Online/Game/Pay 等
}

// 需要组合时,通过接口继承
public interface IExtendAll2 : IExtendPhoto, IExtendRecord, IExtendGame
{
    void Movie(); void Map(); void Pay();
}

ISP vs SRP 的区别

  • SRP 说的是类只做一件事
  • ISP 说的是接口只暴露需要的方法

记忆口诀

接口要小,按需实现;大接口拆小,各取所需。


五、DIP — 依赖倒置原则

Dependence Inversion Principle

核心思想

高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。

通俗理解

你用充电器充电,插头是标准接口(抽象),不管是苹果还是安卓的充电器(具体实现),只要符合接口标准就能用。你不需要为每种手机买专用充电器。

反例:依赖具体类

public class Student
{
    // 每新增一款手机,就要在 Student 里加一个方法 —— 高层依赖低层
    public void PlayiPhone(iPhone phone) { phone.Call(); phone.Text(); }
    public void PlayLumia(Lumia phone)   { phone.Call(); phone.Text(); }
    public void PlayMi(Mi phone)         { phone.Call(); phone.Text(); }
    // 来了 Honor 怎么办?再加一个 PlayHonor?
}

正确做法:依赖抽象

// 抽象层
public abstract class AbstractPhone
{
    public abstract void Call();
    public abstract void Text();
}

// 高层模块依赖抽象,不依赖具体
public class Student
{
    public void PlayPhone(AbstractPhone phone)  // 参数是抽象类
    {
        phone.Call();
        phone.Text();
    }
}

// 新增手机只需新增类,Student 完全不用改
public class Honor : AbstractPhone
{
    public override void Call() { ... }
    public override void Text() { ... }
}

抽象类 vs 接口

DIP 中的"抽象"可以用抽象类或接口来实现,两者各有适用场景:

// 用接口实现 DIP
public interface IPhotoInterface
{
    void Photo();
    void Video();
}

// 高层只依赖接口,不关心具体实现
IPhotoInterface photo = new iPad();
photo.Photo();
photo.Video();
// 想换成其他设备?只需注入不同的实现类,上层代码不用改

抽象类和接口的选择:

  • 抽象类:有公共实现逻辑可以共享时用(比如多个手机品牌都有相同的 Show() 展示逻辑,放在抽象基类里共享)
  • 接口:纯约束,没有实现,多继承场景用(C# 不支持多继承,但支持实现多个接口)

记忆口诀

依赖抽象不依赖具体;新增功能加类,不改旧代码。


六、LOD — 迪米特法则

Law Of Demeter(也叫最少知识原则)

核心思想

一个对象应该对其他对象保持最少的了解。只和"直接朋友"说话,不和"陌生人"说话。

直接朋友指:当前对象本身、方法参数、方法返回值、成员变量。

通俗理解

你找工作,只需要联系 HR,不需要直接联系每个部门负责人。HR 帮你协调,你不需要了解公司内部结构。

反例:School 直接操作 Student

// 违反迪米特:School 直接操作 Student(陌生人)
public void ManageOther()
{
    foreach (Class c in ClassList)
    {
        // School 直接拿到 StudentList,直接操作 Student
        List<Student> studentList = c.StudentList;
        foreach (Student s in studentList)
        {
            Console.WriteLine(s.StudentName);  // School 不应该直接认识 Student
        }
    }
}

正确做法:通过直接朋友委托

// 遵循迪米特:School 只和 Class 说话
public void Manage()
{
    foreach (Class c in ClassList)
    {
        c.ManageClass();  // School 只调用 Class 的方法,不直接碰 Student
    }
}

// Class 负责管理自己的 Student
public void ManageClass()
{
    foreach (Student s in StudentList)
    {
        s.ManageStudent();  // Class 才是 Student 的直接朋友
    }
}

访问修饰符与迪米特

访问修饰符本质上也是迪米特法则的体现——控制"谁能知道什么":

  • private:只有自己知道(隐私)
  • protected:只有子类知道
  • internal:只有同一程序集知道
  • public:所有人都知道

暴露越少,耦合越低。 设计类时,默认从 private 开始,只在真正需要时才提升可见性。

记忆口诀

只和朋友说话,不认识的别搭理;中间人帮你传话,自己别乱串门。


六大原则总结对比

原则英文缩写一句话总结
单一职责SRP一个类只做一件事
开闭原则OCP扩展加代码,修改不动旧代码
里氏替换LSP子类能无缝替换父类
接口隔离ISP接口要小而专,不强迫实现无用方法
依赖倒置DIP依赖抽象,不依赖具体实现
迪米特法则LOD只和直接朋友交互,降低耦合

记忆口诀:SOLID + LOD,其中 SOLID = SRP + OCP + LSP + ISP + DIP

Codex CLI 手机号验证失败?5 种接码平台实测对比与绕过地区限制的 3 步操作 揭示 Codex CLI 手机号验证失败的真实原因在于上下文污染而非网络问题,分析其通过 ASN、Accept-Language 和 TLS SNI 三重加权风控的机制,并实测对比 5 种接码平台在 DNS 解析路径、ASN 干净度和复用间隔上的差异,提出剥离浏览器指纹、固化 TLS SNI、隔离 阅读详情

相关推荐

AI训练师团队管理运营思路

工具运营AI训练师主要是支撑运营,协助算法和运营提高托管机器人的解决能力,以协助降低业务场景熔断与优化场景识别为核心运营目标,通过算法聚类、标注分析等方式,结合业务知识,提供精准、清晰的标注数据和解决方案,确保训练效果满足需求。过程中需要与算法、运营一块参与模型搭建和数据验收,并且负责核心指标和数据日常的跟踪维护。④针对知识库已有意图进行梳理和分析,反馈运营评估缺失或合并意图优化方向。③对语料数据进行挖掘、清洗,解除缠绕、冗余等问题导致的未识别。①线上case分析,及时发现识别问题导致的托管熔断问题。

qq_25438419的博客 1084

C# 13 中的新增功能

💥C# 13 包括以下新增功能 新的转义序列 - \e , 方法组自然类型改进, 对象初始值设定项中的隐式索引器访问。总体来说改动不大,修修补补。

李赛赛的专栏 1603

聚类分析(超全超详细版)

聚类分析是一种典型的无监督学习, 用于对未知类别的样本进行划分,将它们按照一定的规则划分成若干个类族,把相似(距高相近)的样本聚在同一个类簇中, 把不相似的样本分为不同类簇,从而揭示样本之间内在的性质以及相互之间的联系规律 聚类算法在银行、零售、保险、医学、军事等诸多领域有着广泛的应用 聚类分析基础 聚类分析的概念 聚类分析是根据在数据中发现的描述对象及其关系的信息,将数据对象分组。目的是...

Gfqwy2021 22万+

浅谈 C# 13 中的 params 集合

综上所述C# 13 中的 params 集合变得类型更灵活,满足更复杂的应用场景,并且性能得到了进一步的提升。params适用于参数个数动态变化的场景,例如日志、数学计算或格式化输出等,减少冗余代码,增强方法通用性。/// 如创建大型数据集、分配内存资源等,避免在每次基准测试迭代中重复初始化带来的性能干扰。转载于: https://www.cnblogs.com/Can-daydayup/p/18780354。: 每次操作分配的内存(仅托管内存,包含所有内容,1KB = 1024B)。

weixin_42529328的博客 79

手把手教你获取全国街道级GeoJSON数据:前端地图开发必备技巧

本文详细介绍了获取全国街道级GeoJSON数据的多种方法,从前端地图开发的实际需求出发,涵盖了免费获取省市县级数据的工具如阿里云DataV.GeoAtlas和HashTang,以及进阶的街道级数据获取方案,包括使用Bigemap GIS Office和专业数据采购。文章还提供了数据处理与优化技巧,帮助开发者高效使用GeoJSON数据进行地图可视化。

weixin_29053383的博客 288

Adobe Acrobat Pro(Adobe PDF) - 使用技巧

Adobe Acrobat Pro为Adobe出品的PDF查看和编辑软件,下文简称Adobe PDF,该软件功能强大,拥有查看PDF、编辑PDF、打印PDF、导出PDF、合并文件、组织页面、文本标注、注释、动作向导、等功能。本文介绍Adobe PDF的一些使用技巧,最后介绍软件设置。

NSJim的博客 4万+

提高 C# 的生产力:C# 13 更新完全指南

预计在 2024 年 11 月,C# 13 将与 .NET 9 一起正式发布。今年的 C# 更新主要集中在ref struct上进行了许多改进,并添加了许多有助于进一步提高生产力的便利功能。本文将介绍预计将在 C# 13 中添加的功能。注意:目前 C# 13 还未正式发布,因此以下内容可能会发生变化。C# 正在年复一年地进化,对我来说 C# 13 的更新中实现了许多非常实用且方便的功能,解决了不少实际的痛点。期待 .NET 9 和 C# 13 的正式发布~hez2010。

sdgfafg_25的博客 1443

C# 操作Excel的时候,出现"被呼叫方拒绝接受呼叫的异常"的解决方案(参考官方给出的解决方案)

首先官方有对这个错误给出解释和解决方案,连接如下: https://docs.microsoft.com/zh-cn/previous-versions/ms228772(v=vs.120)#%E5%8F%AF%E9%9D%A0%E7%BC%96%E7%A8%8B 简单来说,貌似是线程问题,我猜。。。 之前我尝试着在代码中添加 Thread.Sleep(1000); 来进行解决,这种办...

Ck_Max的博客 5767

.net C# 13中你应该知道的新增功能

C#(发音为“C sharp”)是由Microsoft开发的一种通用的面向对象的编程语言。它广泛用于构建各种类型的软件应用程序,从桌面应用程序到 Web 服务、游戏和移动应用程序。C# 是 .NET 框架的一部分,它为开发人员提供了一组丰富的库和工具。C# 最初于 2000 年推出,此后经历了多个版本的发展,每次迭代都引入了新功能和改进。它与 C 和 C++ 等语言有相似之处,但它也融合了 Java 等语言的概念。

2401_82584055的博客 1390

ABAP BOM展开避坑指南:CS_BOM_EXPL_MAT_V2函数参数配置详解

本文深入解析了SAP ABAP开发中用于物料清单展开的核心函数CS_BOM_EXPL_MAT_V2。针对其复杂的参数配置,如CAPID、STLAN、DATUV和MEHRS,提供了详细的避坑指南和最佳实践,帮助开发者避免数据错误与性能陷阱,实现高效、准确的BOM多层展开。

pea55的博客 850

基于 YOLOv26 的高速抛物识别系统:微小目标检测

本文提出了一种基于YOLOv26的高速抛物识别系统,专注于微小目标检测。系统采用多模块协同架构,包括视频预处理、YOLOv26检测、目标跟踪和抛物行为分析等模块。关键技术包括YOLOv26s模型检测、DeepSORT目标跟踪和边缘计算部署。通过构建包含多种抛物类型的专业数据集,并应用数据增强技术提升模型性能。系统实现了车辆检测、微小抛物目标识别、抛物轨迹分析和风险等级评估等功能,可实时检测高速公路上的抛物行为并触发告警,为交通管理提供智能化解决方案。

一键难忘的博客 632

C# 13 支持 Partial Property 了

C# 13 支持 Partial Property 了IntroC# 13 扩展了 partial 的支持,实现了对 partial property 的支持,得益于 partial property 的支持,正则表达式 source generator 之前只支持 partial method,在 .NET 9 也将支持 partial propertySample来看简单的使用示例:file...

farway000的博客 202

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C# 13中你应该知道的新增功能

C#(发音为“C sharp”)是由Microsoft开发的一种通用的面向对象的编程语言。它广泛用于构建各种类型的软件应用程序,从桌面应用程序到 Web 服务、游戏和移动应用程序。 C# 是 .NET 框架的一部分,它为开发人员提供了一组丰富的库和工具。C# 最初于 2000 年推出,此后经历了多个版本的发展,每次迭代都引入了新功能和改进。它与 C 和 C++ 等语言有相似之处,但它也融合了 Ja...

dotNET跨平台 416

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

C# 13 中的新增功能实操

通过合理设置优先级,开发者可以在保持代码兼容性的同时,优化编译器的选择逻辑。在 C# 13 中,params 的改进使其从可变数量的数组参数升级为可变数量的集合类型参数。C# 13 中的 params 集合变得类型更灵活,满足更复杂的应用场景,并且性能得到了进一步的提升。库作者可以使用该属性确保新的、更好的重载比现有的重载更受青睐。后面的下一个字符是有效的十六进制数字,则那些字符会成为转义序列的一部分。类型不能声明为泛型或方法的类型参数。调用方法时需显式传递数组或数组元素类型的参数的逗号分隔列表。

kfashfasf的博客 1290

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

c#13新特性

我想这个特性是很大的一个改变,或许可以改进C#代码的组织方式,有望提高代码的可读性、可维护性和表现力。通过允许开发人员在不修改原始代码的情况下向现有类添加功能,它可以促进代码重用并减少修改原始类的需要。另外据了解,这个特性以及相关特性,例如扩展接口等等,并不会在C#13(.NET9)中完整的放出来,而是会在后续版本中逐渐解锁。

A_nanda的博客 669

C# 13 编译器还真是个大聪明

文章《C# 13 编译器还真是个大聪明》探讨了C# 13编译器在处理类成员赋值和异步函数调用时的行为。作者指出,编译器在类成员通过构造函数间接赋值时,仍会发出CS8618警告,尽管赋值确实发生。此外,编译器在处理Action和Func<Task>类型时存在混淆,允许将异步闭包传递给期望同步闭包的函数,导致潜在的运行时错误。作者建议通过改进函数命名和重载来避免此类问题,并强调编译器应更严格地检查类型匹配,以防止代码缺陷。以上摘要由AI生成。

Liigo's blog 1285

C# 13 Ref Struct Interfaces

C# 13 Ref Struct InterfacesIntroC# 从 7.2 开始引入了 ref struct,ref struct 只能分配在栈上,不能被装箱,因为不能被装箱之前的版本中 ref struct 是不能实现接口的,在转成接口的时候会导致发生装箱,这是不被允许的,而我们在做一些设计的时候往往会使用到接口,用接口定义契约contract,C# 13 开始我们可以允许 ref st...

dotNET跨平台 220

C# 13 新特性 params collection

C# 13 新特性 params collectionIntroC# 12 中支持了 collection expression, 统一和简化了常见集合的赋值语法,我们可以使用 [1, 2, 3] 这样的语法来初始化集合,C# 13 扩展了 params 的用法,在之前的版本中我们只能使用 params int[] ,但是从 C# 13 开始,我们也可以使用 params List<int&...

dotNET跨平台 289
上一篇: 10-C#
下一篇: 15-C#
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值