C#面向对象编程:类(Class)核心概念与实战技巧
1. 类Class基础概念解析在C#编程语言中类Class是面向对象编程OOP的核心构建块。它就像是一个自定义的数据类型蓝图定义了对象的结构和行为。我刚开始学习C#时对类的理解就是把数据和操作数据的方法打包在一起的容器。一个典型的类包含以下核心组成部分字段Fields存储数据的变量属性Properties控制对字段的访问方法Methods定义类的行为构造函数Constructors初始化对象的特殊方法事件Events用于通知其他对象的机制// 最简单的类定义示例 public class Person { // 字段 private string name; // 属性 public string Name { get { return name; } set { name value; } } // 方法 public void Greet() { Console.WriteLine($Hello, my name is {Name}); } // 构造函数 public Person(string name) { this.name name; } }提示在Visual Studio中输入prop然后按Tab键可以快速生成属性代码片段这是提高编码效率的小技巧。2. 类的核心特性深入探讨2.1 访问修饰符的实战应用访问控制是类的关键特性之一C#提供了以下几种访问修饰符修饰符可访问范围使用场景public无限制需要被其他类广泛使用的成员private仅限类内部实现细节不希望外部访问protected类及其派生类为继承设计的成员internal同一程序集组件内部使用的功能protected internal程序集或派生类特殊框架设计需求在实际项目中我遵循最小权限原则默认使用private只有确实需要暴露的成员才提升访问级别。这样可以减少意外的外部依赖提高代码的健壮性。2.2 属性和字段的选择策略初学者常常困惑于何时使用字段何时使用属性。我的经验法则是永远使用属性暴露数据即使是最简单的get/set仅在类内部使用私有字段存储实际数据需要计算或验证时使用属性// 不好的实践直接暴露字段 public string Name; // 好的实践使用属性 private string name; public string Name { get name; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(Name cannot be empty); name value; } }注意从C# 3.0开始可以使用自动实现的属性简化代码public string Name { get; set; }但在需要添加逻辑时可以随时扩展而不破坏现有代码。3. 类的高级特性实战3.1 构造函数的最佳实践构造函数是类初始化的关键点我总结了几个实用技巧提供最少参数的构造函数保持简洁使用可选参数或方法链来支持多种初始化方式对必要参数进行验证public class Order { public int Id { get; } public DateTime Date { get; } public decimal Amount { get; } // 主构造函数 public Order(int id, DateTime date, decimal amount) { if (id 0) throw new ArgumentException(ID must be positive); if (amount 0) throw new ArgumentException(Amount cannot be negative); Id id; Date date; Amount amount; } // 便捷构造函数 public Order(int id) : this(id, DateTime.Now, 0) {} }3.2 静态类与静态成员静态类static class是不能实例化的类常用于工具类或扩展方法。静态成员属于类本身而非实例。使用场景数学计算工具如Math类全局配置访问工厂方法public static class StringHelper { public static bool IsValidEmail(string email) { return Regex.IsMatch(email, ^[^\s][^\s]\.[^\s]$); } } // 使用方式 bool isValid StringHelper.IsValidEmail(testexample.com);警告过度使用静态成员会导致代码难以测试和维护特别是在需要模拟依赖的情况下。仅在确实需要全局访问且无状态时使用。4. 面向对象原则在类设计中的应用4.1 封装的艺术封装是OOP的三大支柱之一另外两个是继承和多态。好的封装应该隐藏实现细节暴露最小必要接口确保对象始终处于有效状态我在项目中常用的封装技巧使用readonly字段防止意外修改将集合属性暴露为IEnumerable 而非List使用工厂方法控制对象创建public class BankAccount { private readonly string accountNumber; private decimal balance; public string AccountNumber accountNumber; public decimal Balance balance; private BankAccount(string accountNumber) { this.accountNumber accountNumber; } public static BankAccount CreateNew(string accountNumber) { if (!IsValidAccountNumber(accountNumber)) throw new ArgumentException(Invalid account number); return new BankAccount(accountNumber); } public void Deposit(decimal amount) { if (amount 0) throw new ArgumentException(Amount must be positive); balance amount; } // 其他方法... }4.2 继承与组合的选择很多初学者过度使用继承实际上组合优于继承是更现代的设计理念。我的选择标准使用继承当确实是is-a关系需要多态行为基类稳定且不会频繁变更使用组合当只是has-a关系需要灵活替换组件避免继承层次过深// 继承示例 public class Animal { /* ... */ } public class Dog : Animal { /* ... */ } // 组合示例 public class Car { private Engine engine; private ListWheel wheels; public Car(Engine engine, IEnumerableWheel wheels) { this.engine engine; this.wheels wheels.ToList(); } }5. 实际项目中的类设计经验5.1 领域模型类的设计模式在业务系统开发中我常用以下几种模式设计类贫血模型 vs 富模型贫血模型只有数据没有行为常见于早期Java/C#项目富模型数据和行为在一起更符合OO理念值对象模式不可变通过相等性而非标识比较如Money、Address等类型实体模式有唯一标识可变状态如User、Order等// 值对象示例 public class Address : IEquatableAddress { public string Street { get; } public string City { get; } public string ZipCode { get; } public Address(string street, string city, string zipCode) { Street street; City city; ZipCode zipCode; } public bool Equals(Address other) Street other.Street City other.City ZipCode other.ZipCode; // 其他相等性实现... } // 实体示例 public class Customer { public Guid Id { get; } public string Name { get; private set; } public Address ShippingAddress { get; private set; } public Customer(string name, Address shippingAddress) { Id Guid.NewGuid(); Name name; ShippingAddress shippingAddress; } public void UpdateShippingAddress(Address newAddress) { ShippingAddress newAddress ?? throw new ArgumentNullException(nameof(newAddress)); } }5.2 类的大小与单一职责一个常见的误区是创建上帝类包含太多功能的超大类。我遵循以下原则控制类的大小单一职责原则SRP一个类只做一件事如果类的方法超过15-20个考虑拆分如果类的代码超过300-500行考虑重构判断方法能否用一句话清晰描述这个类的职责如果不能说明职责过多。6. C#类的最新语言特性6.1 记录类型RecordC# 9.0引入了记录类型特别适合不可变数据模型public record Person(string FirstName, string LastName); // 使用 var person1 new Person(John, Doe); var person2 person1 with { LastName Smith }; // 非破坏性修改记录类型自动提供值相等性比较基于属性的ToString()With表达式支持解构功能6.2 主构造函数Primary ConstructorsC# 12进一步简化了类定义public class Student(string name, int age) { public string Name { get; } name; public int Age { get; } age; public override string ToString() ${Name}, {Age} years old; }7. 常见陷阱与调试技巧7.1 对象引用问题新手常犯的错误是混淆值类型和引用类型var list1 new Listint { 1, 2, 3 }; var list2 list1; // list2和list1指向同一个对象 list2.Add(4); Console.WriteLine(list1.Count); // 输出4不是3解决方法对于引用类型需要时创建副本使用不可变集合System.Collections.Immutable实现ICloneable接口谨慎使用7.2 相等性比较的坑默认情况下类的相等性比较是基于引用的。要实现值比较需要重写Equals方法重写GetHashCode方法实现IEquatable 接口public class Product : IEquatableProduct { public int Id { get; } public string Name { get; } public Product(int id, string name) { Id id; Name name; } public override bool Equals(object obj) Equals(obj as Product); public bool Equals(Product other) other ! null Id other.Id Name other.Name; public override int GetHashCode() HashCode.Combine(Id, Name); }8. 性能优化注意事项8.1 避免过度封装虽然封装是好的但过度封装会影响性能// 不好的做法多层属性访问 public class A { public B B { get; } new B(); } public class B { public C C { get; } new C(); } public class C { public int Value { get; set; } } var value a.B.C.Value; // 每次访问都要通过多个属性优化方法对于高频访问的深层属性考虑缓存在性能关键路径上减少间接访问8.2 结构体struct的使用场景对于小型、不可变、频繁创建销毁的类型考虑使用结构体而非类public struct Point { public double X { get; } public double Y { get; } public Point(double x, double y) { X x; Y y; } }使用结构体的条件大小不超过16字节不可变不需要继承值语义更合适9. 单元测试最佳实践9.1 可测试的类设计编写易于测试的类需要注意依赖通过构造函数注入而非静态方法针对接口编程避免在构造函数中进行复杂操作public class OrderProcessor { private readonly IPaymentGateway paymentGateway; private readonly IInventoryService inventoryService; public OrderProcessor(IPaymentGateway paymentGateway, IInventoryService inventoryService) { this.paymentGateway paymentGateway; this.inventoryService inventoryService; } public bool ProcessOrder(Order order) { // 使用注入的服务处理订单 } }9.2 测试私有方法通常只测试公共接口但如果必须测试私有方法改为protected并通过子类测试使用InternalsVisibleTo特性使用反射最后选择[assembly: InternalsVisibleTo(Tests)] public class MyClass { internal int InternalCalculate() { /* ... */ } }10. 实际案例用户管理系统让我们通过一个用户管理系统的例子整合所学知识public class User : IEquatableUser { public Guid Id { get; } public string Username { get; } public string Email { get; private set; } public DateTime CreatedAt { get; } public DateTime? LastLogin { get; private set; } private readonly ListRole roles new(); public IReadOnlyListRole Roles roles.AsReadOnly(); public User(string username, string email) { if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException(Username cannot be empty); if (!EmailValidator.IsValid(email)) throw new ArgumentException(Invalid email address); Id Guid.NewGuid(); Username username; Email email; CreatedAt DateTime.UtcNow; } public void UpdateEmail(string newEmail) { if (!EmailValidator.IsValid(newEmail)) throw new ArgumentException(Invalid email address); Email newEmail; } public void RecordLogin() { LastLogin DateTime.UtcNow; } public void AddRole(Role role) { if (role null) throw new ArgumentNullException(nameof(role)); if (!roles.Contains(role)) roles.Add(role); } public bool RemoveRole(Role role) { return roles.Remove(role); } // 相等性实现... } public record Role(string Name, string Description);这个示例展示了封装业务规则用户名、邮箱验证控制可变性大部分属性只读通过方法修改集合属性的安全暴露记录类型的使用领域逻辑的集中管理11. 进阶主题模式匹配与类C# 7.0引入的模式匹配可以简化基于类类型的条件逻辑public abstract class Shape { /* ... */ } public class Circle : Shape { public double Radius { get; } /* ... */ } public class Rectangle : Shape { public double Width { get; } public double Height { get; } /* ... */ } public double CalculateArea(Shape shape) { return shape switch { Circle c Math.PI * c.Radius * c.Radius, Rectangle r r.Width * r.Height, _ throw new ArgumentException(Unknown shape type) }; }12. 类与异步编程现代C#开发中类的方法经常需要支持异步操作public class DataService { private readonly HttpClient httpClient; public DataService(HttpClient httpClient) { this.httpClient httpClient; } public async Taskstring FetchDataAsync(string url) { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException(URL cannot be empty); try { var response await httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } catch (HttpRequestException ex) { throw new DataServiceException(Failed to fetch data, ex); } } }关键点异步方法命名以Async为后缀参数验证在await之前正确处理异常并转换为领域异常13. 源代码生成与类设计C#的源代码生成功能可以自动生成类代码// 使用partial类配合源代码生成器 public partial class Person { public string FirstName { get; } public string LastName { get; } public Person(string firstName, string lastName) { FirstName firstName; LastName lastName; } } // 源代码生成器生成的代码 partial class Person { public string FullName ${FirstName} {LastName}; }常见应用场景序列化/反序列化逻辑INotifyPropertyChanged实现DTO到模型的映射14. 类设计中的SOLID原则14.1 单一职责原则SRP一个类应该只有一个引起变化的原因。例如将用户存储和用户验证分离// 违反SRP public class UserService { public void AddUser(User user) { /* 保存到数据库 */ } public bool ValidatePassword(string password) { /* 密码规则验证 */ } } // 遵循SRP public class UserRepository { public void Add(User user) { /* 保存到数据库 */ } } public class PasswordValidator { public bool IsValid(string password) { /* 密码规则验证 */ } }14.2 开闭原则OCP对扩展开放对修改关闭。使用策略模式示例public interface IDiscountStrategy { decimal ApplyDiscount(decimal amount); } public class NoDiscount : IDiscountStrategy { /* ... */ } public class PercentageDiscount : IDiscountStrategy { /* ... */ } public class FixedAmountDiscount : IDiscountStrategy { /* ... */ } public class Order { private readonly IDiscountStrategy discountStrategy; public Order(IDiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } public decimal CalculateTotal(decimal subtotal) { return subtotal - discountStrategy.ApplyDiscount(subtotal); } }15. 领域驱动设计DDD中的类15.1 聚合根设计聚合根是DDD中的核心概念负责维护一组相关对象的一致性public class Order : IAggregateRoot { private readonly ListOrderItem items new(); public Guid Id { get; } public Customer Customer { get; } public IReadOnlyCollectionOrderItem Items items.AsReadOnly(); public Order(Guid id, Customer customer) { Id id; Customer customer; } public void AddItem(Product product, int quantity) { if (product null) throw new ArgumentNullException(nameof(product)); if (quantity 0) throw new ArgumentException(Quantity must be positive); var existingItem items.FirstOrDefault(i i.Product.Id product.Id); if (existingItem ! null) { existingItem.IncreaseQuantity(quantity); } else { items.Add(new OrderItem(product, quantity)); } } // 其他领域逻辑... }15.2 领域事件使用领域事件处理跨聚合的业务逻辑public class Order { // ... public void Complete() { // 订单完成逻辑... AddDomainEvent(new OrderCompletedEvent(Id, DateTime.UtcNow)); } private readonly ListIDomainEvent domainEvents new(); public IReadOnlyCollectionIDomainEvent DomainEvents domainEvents.AsReadOnly(); protected void AddDomainEvent(IDomainEvent domainEvent) { domainEvents.Add(domainEvent); } public void ClearDomainEvents() { domainEvents.Clear(); } }16. 类与依赖注入现代C#开发中类设计需要考虑依赖注入(DI)public interface ILogger { void Log(string message); } public class FileLogger : ILogger { /* ... */ } public class ProductService { private readonly ILogger logger; public ProductService(ILogger logger) { this.logger logger ?? throw new ArgumentNullException(nameof(logger)); } public void AddProduct(Product product) { try { // 添加产品逻辑 logger.Log($Product {product.Id} added); } catch (Exception ex) { logger.Log($Error adding product: {ex.Message}); throw; } } }最佳实践依赖于抽象接口而非具体实现所有依赖通过构造函数注入避免服务定位器反模式17. 类的版本控制与兼容性当类需要演进时保持向后兼容的技巧添加新方法而非修改现有方法使用过时标记[Obsolete]而非直接删除成员为重大变更引入新类而非修改现有类public class Customer { [Obsolete(Use Email property instead)] public string GetEmailAddress() Email; public string Email { get; set; } // 新功能 public IReadOnlyListAddress Addresses { get; } }18. 调试与诊断技巧18.1 重写ToString()为类重写ToString()可以极大简化调试public override string ToString() { return ${GetType().Name} [Id{Id}, Name{Name}, Email{Email}]; }18.2 使用DebuggerDisplay更精细地控制调试器中的显示[DebuggerDisplay({DebuggerDisplay,nq})] public class Order { public int Id { get; } public decimal Total { get; } private string DebuggerDisplay $Order #{Id} (Total: {Total:C}); }19. 性能敏感场景的类优化19.1 对象池模式对于频繁创建销毁的类使用对象池减少GC压力public class ObjectPoolT where T : new() { private readonly ConcurrentBagT pool new(); public T Get() { return pool.TryTake(out T item) ? item : new T(); } public void Return(T item) { pool.Add(item); } } // 使用 var pool new ObjectPoolMemoryStream(); var stream pool.Get(); try { // 使用stream... } finally { pool.Return(stream); }19.2 结构体替代小型类对于小型、短生命期的数据容器考虑使用结构体public struct Point3D { public double X; public double Y; public double Z; public Point3D(double x, double y, double z) { X x; Y y; Z z; } }20. 跨平台开发中的类设计在.NET跨平台开发中类设计需要考虑避免平台特定API使用依赖注入抽象平台功能考虑可移植类库(PCL)或.NET Standardpublic interface IFileSystem { Stream OpenRead(string path); bool FileExists(string path); } // 平台特定实现 public class WindowsFileSystem : IFileSystem { /* ... */ } public class LinuxFileSystem : IFileSystem { /* ... */ } public class DataLoader { private readonly IFileSystem fileSystem; public DataLoader(IFileSystem fileSystem) { this.fileSystem fileSystem; } public byte[] LoadData(string filePath) { if (!fileSystem.FileExists(filePath)) throw new FileNotFoundException(); using var stream fileSystem.OpenRead(filePath); using var memoryStream new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } }

相关新闻

ICE-BA论文解析:增量、一致且高效的视觉惯性SLAM束调整

ICE-BA论文解析:增量、一致且高效的视觉惯性SLAM束调整

我最初接触ICE-BA这篇论文,是冲着它的标题去的:Incremental, Consistent and Efficient Bundle Adjustment for Visual-Inertial SLAM。做VIO的同学都知道,Bundle Adjustment(BA)是后端优化的核心,但传统全…

2026/10/14 0:23:48 阅读更多 →
Flask人脸识别签到系统源码解析:从环境搭建到模型调优

Flask人脸识别签到系统源码解析:从环境搭建到模型调优

简介:这是一套面向高校计算机相关专业学生与Python开发者的毕业设计级项目源码,主题为基于深度学习的人脸识别签到系统,适合作为课程设计、毕设参考或人脸识别入门实战案例。压缩包共27个文件,约102.26MB,以8个Python脚…

2026/10/14 0:23:48 阅读更多 →
Kotlin noarg与allopen插件:原理、配置与实战避坑指南

Kotlin noarg与allopen插件:原理、配置与实战避坑指南

1. 从一次序列化报错说起:为什么数据类需要"无参构造"第一次在Kotlin项目里用Jackson做JSON反序列化的时候,我遇到了一个非常典型的报错:Cannot construct instance of xxx (no Creators, like default constructor, exist)。当时我…

2026/10/14 0:23:48 阅读更多 →

最新新闻

Claude 看板与动画工具实战:对话式办公套件搭建指南

Claude 看板与动画工具实战:对话式办公套件搭建指南

1. 从单点对话到办公套件:这次更新到底改了什么Claude 最早给人的印象就是一个“会聊天的模型”,你问它答,顶多帮你改改文案、写写代码。但最近这一波更新,方向明显变了——它开始往“办公套件”的路子上走。所谓看板工具和动画工…

2026/10/14 9:47:26 阅读更多 →
小白程序员转行AI必看:Agent开发与大模型开发的区别与学习路径

小白程序员转行AI必看:Agent开发与大模型开发的区别与学习路径

本文对比了大模型算法工程师和Agent开发工程师的薪资、工作内容、学习门槛及发展前景。指出大模型算法岗薪资高但门槛极高,适合深入研究AI模型;而Agent开发岗入门门槛低,适合将AI应用于实际业务场景,是当前及未来的热门方向。建议…

2026/10/14 9:47:26 阅读更多 →
Claude 办公套件更新:看板与动画工具实战指南

Claude 办公套件更新:看板与动画工具实战指南

1. 从单点对话到办公套件:这次更新到底改了什么Claude 最早给人的印象就是一个"能聊天的模型",你问它答,偶尔帮你改改文案、写写代码。但最近这一波更新,方向明显变了——它不再满足于做一个对话框里的助手,…

2026/10/14 9:47:26 阅读更多 →
菲律宾客服外包不是四选一:把服务模式做成阶段性组合

菲律宾客服外包不是四选一:把服务模式做成阶段性组合

菲律宾客服模式怎么选?一个直接的判断可以作为起点:工单少、波动大且问题标准化时,先评估共享坐席;业务稳定并需要持续沉淀产品知识时,倾向专属团队;智能硬件等复杂产品需要菲律宾英语一线与中国技术团队形…

2026/10/14 9:47:26 阅读更多 →
CSS阴影效果深度解析与性能优化指南

CSS阴影效果深度解析与性能优化指南

1. 为什么CSS阴影效果总是让人头疼?作为前端开发中最常用的视觉增强手段之一,CSS阴影效果看似简单,实则暗藏玄机。新手常遇到的典型问题包括:阴影效果不自然、性能消耗大、浏览器兼容性差、多层阴影叠加混乱等。这些问题的根源在于…

2026/10/14 9:47:26 阅读更多 →
模型量化:4bit、8bit量化原理与实践

模型量化:4bit、8bit量化原理与实践

📝 本章学习目标:通过本章学习,你将全面掌握"模型量化:4bit、8bit量化原理与实践"这一核心主题,建立系统性认知。一、引言:为什么这个话题如此重要 在人工智能快速发展的今天,模型量化…

2026/10/14 9:46:26 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →