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

【层面一】C#语言基础和核心语法-01(类型系统/面向对象/异常处理)

文章目录

  • 1 类型系统
    • 1.1 为什么需要类型?
    • 1.2 .NET 类型系统的两大支柱:CTS 和 CLS
    • 1.3 最根本的分类:值类型 vs 引用类型
    • 1.4 内置类型 vs. 自定义类型
    • 1.5 类型转换
    • 1.6 通用基类:System.Object
  • 2 面向对象编程
    • 2.1 类和对象
    • 2.2 接口和类
    • 2.3 访问修饰符
    • 2.4 (OOP)三大特性:封装、继承、多态
    • 2.5 其他成员:索引器、运算符重载
      • 2.5.1 索引器:让对象像数组一样访问
      • 2.5.2 运算符重载:让对象支持数学运算
  • 3. 异常处理

这是所有.NET开发的基石,必须牢固掌握。

1 类型系统

1.1 为什么需要类型?

类型系统就是一套规则,它告诉编译器和我们:

  1. 数据是什么(是数字、文本、还是自定义对象?)
  2. 能对它做什么(能计算吗?能比较吗?能调用它的方法吗?)
  3. 它占多少空间(在内存中如何布局)
  4. 它如何与其他数据交互(如何转换、继承、实现接口)

类型系统为代码提供了结构、安全性和可读性

1.2 .NET 类型系统的两大支柱:CTS 和 CLS

为了实现“跨语言”的宏伟目标,.NET 制定了两个标准:

  1. 公共类型系统 - CTS

    • 定义: 一套所有 .NET 语言都必须遵守的关于类型的定义、行为和关系的规范。
    • 目的:确保在一种语言中定义的类型(如 C# 的 class)可以在另一种语言中(如 F#)无缝使用。它定义了所有类型最终都派生自 System.Object,规定了什么是类、接口、委托、值类型、引用类型等。
    • 比喻:CTS 就像是欧盟的标准,规定了所有成员国生产的电器插头形状、电压标准。这样德国产的电器拿到法国就能直接用。
  2. 公共语言规范 - CLS

    • 定义:CTS 的一个子集。它定义了所有 .NET 语言都必须支持的最小功能集

    • 目的:确保开发者编写的代码可以被任何其他 .NET 语言使用。如果你希望代码是“符合 CLS 的”,就应该避免使用某些语言特有的特性(如 C# 的 uint 无符号整数,因为有些语言不支持)。

    • 比喻:CLS 就像是欧盟标准下的最低安全标准。一个产品只要满足这个最低标准,就可以在欧盟所有国家销售。开发者可以选择只使用这些最低标准特性,来保证最大的互操作性。

1.3 最根本的分类:值类型 vs 引用类型

这是 .NET 类型系统最核心、最重要的区别。几乎所有其他特性都源于此。

特性值类型引用类型
存储位置托管堆
存储内容直接存储数据本身存储数据的地址(引用)
赋值行为复制整个数据(创建副本)复制引用(指向同一对象)
默认值所有字段为 0 或 nullnull
继承隐式密封(sealed),不能作为基类可以派生其他类
内存管理超出作用域时立即被回收由垃圾回收器(GC)管理
例子int, float, bool, char, struct, enumclass, interface, delegate, array, string

比喻

  • 值类型就像你的「身份证」

    • 你复印身份证给别人,别人拿到的是副本。修改复印件,不影响你原来的身份证。

    • 身份证本身就在你手里(栈上)。

  • 引用类型就像「银行的保险箱」

    • 你告诉朋友保险箱的号码和钥匙(引用),你们用的是同一个保险箱。朋友取走里面的东西,你再去就没了。

    • 保险箱本身在银行金库里(堆上),你手里只拿着钥匙。

// 值类型示例 (struct)
public struct Point
{public int X;public int Y;
}Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1; // 复制!p2 是 p1 的一个完整副本p2.X = 100;    // 修改 p2 不会影响 p1
Console.WriteLine(p1.X); // 输出 10
Console.WriteLine(p2.X); // 输出 100// 引用类型示例 (class)
public class Person
{public string Name;
}Person person1 = new Person { Name = "Alice" };
Person person2 = person1; // 复制引用!现在 person2 和 person1 指向同一个对象person2.Name = "Bob";     // 通过 person2 修改对象
Console.WriteLine(person1.Name); // 输出 "Bob",因为 person1 也指向同一个对象
Console.WriteLine(person2.Name); // 输出 "Bob"

1.4 内置类型 vs. 自定义类型

  1. 内置类型(基础类型)

.NET 提供了一组现成的、最常用的类型,它们在 C# 中有关键字对应:

C# 关键字.NET 类型分类说明
intSystem.Int32值类型32 位整数
longSystem.Int64值类型64 位整数
floatSystem.Single值类型32 位浮点数(需加 f 后缀)
doubleSystem.Double值类型64 位浮点数
decimalSystem.Decimal值类型128 位高精度小数(用于金融,需加 m 后缀)
boolSystem.Boolean值类型布尔值(true/false)
charSystem.Char值类型单个 Unicode 字符
stringSystem.String引用类型不可变的 Unicode 字符串序列
objectSystem.Object引用类型所有类型的终极基类

注意

string 是特殊的引用类型。它的行为有时像值类型(因为它是不可变的),任何修改操作都会产生一个新的字符串对象。

  1. 自定义类型
    开发者可以创建自己的复杂类型,这是面向对象编程的核心:
类型关键字主要目的分类
class定义数据和行为的蓝图,是OOP的主力引用类型
结构struct定义轻量级的、行为简单的数据聚合值类型
枚举enum定义一组命名的常数值类型
接口interface定义一套公共行为的契约引用类型
委托delegate定义方法签名,用于回调和方法引用引用类型

1.5 类型转换

在不同类型之间转换是常见操作。

  1. 隐式转换

    • 由编译器自动进行的安全转换,不会丢失信息。

    • 规则:从小范围类型转向大范围类型。

    • 示例:int i = 10; long l = i; (int -> long)

  2. 显式转换(强制转换)

    • 可能丢失信息或失败,需要开发者明确指定。

    • 语法:(目标类型)源变量

    • 示例:double d = 3.14; int i = (int)d; (double -> int, 值变为 3)

    • 风险:可能导致精度丢失或溢出。

  3. 使用转换方法

    • ToString(): 任何对象都可以转换为字符串。

    • Parse() / TryParse(): 将字符串转换为其他类型(如 int.Parse(“123”))。

    • Convert 类: Convert.ToInt32(), Convert.ToDateTime() 等,功能更丰富。

  4. as 和 is 运算符

    • as: 用于引用类型之间的安全转换,失败则返回 null。

      object obj = new Person();
      Person p = obj as Person; // 安全转换
      if (p != null) { … }

    • is: 检查对象是否与给定类型兼容,返回 bool。C# 7.0 后支持模式匹配。

      if (obj is Person p) // 检查的同时转换
      {
      // 可以直接使用 p
      }

1.6 通用基类:System.Object

所有类型都直接或间接继承自 Object 类。它提供了几个最基本的方法:

  • Equals(): 判断两个对象是否“逻辑相等”。

  • GetHashCode(): 获取对象的哈希码(用于哈希表等数据结构)。

  • ToString(): 返回对象的字符串表示形式(默认返回类型全名,常被重写)。

  • GetType(): 非常重要!返回当前实例的准确类型(Type 对象)。用于反射。

  • MemberwiseClone(): 创建当前对象的浅表副本。


总结:类型系统带来的四大好处

  1. 安全性:编译器可以在编译时检查类型错误(例如,试图将字符串除以数字),将大量错误扼杀在摇篮中。

  2. 可读性:代码即文档。看到变量的类型,就能清晰地知道它的用途和能进行的操作。

  3. 内存管理:编译器知道类型的大小和生命周期,从而能高效地分配内存(值类型在栈上,引用类型在堆上)。

  4. 抽象与组织:通过类、接口等机制,允许开发者创建复杂的领域模型,更好地组织代码。


2 面向对象编程

2.1 类和对象

这是OOP最基础的概念,理解它就能理解OOP的整个世界。

  1. 类 - 蓝图
  • 是什么类是一个模板、一个蓝图、一个定义。它本身不是一个具体的东西,它只描述一类事物应该有什么样的特征和行为。

  • 生活比喻建筑设计图。图纸上定义了房子的户型、面积、有几个卧室、几个卫生间。但图纸本身不能住人。

  • 代码中:类定义了属性(数据/特征)和方法(行为/功能)。

// 这是一个“狗”类的蓝图
public class Dog
{// 属性 (特征)public string Name { get; set; } // 名字public string Breed { get; set; } // 品种// 方法 (行为)public void Bark(){Console.WriteLine($"{Name} 说:汪汪!");}public void Eat(string food){Console.WriteLine($"{Name} 正在吃 {food}");}
}

这个 Dog 类就像一张蓝图,世界上并没有一只叫“Dog”的狗,它只是规定了“狗”应该有名字、品种,会叫、会吃

  1. 对象 - 房子
  • 是什么对象是类的一个具体实例。它是根据蓝图真正建造出来的、实实在在的东西。

  • 生活比喻:根据建筑设计图建造出来的一栋真实的房子。你可以住进去,可以装修它。

  • 代码中:使用 new 关键字来根据类创建对象。这个过程叫实例化

// 根据“狗”的蓝图,创建两只真实的狗(对象)
Dog myDog = new Dog(); // new 关键字就是“建造”的过程
myDog.Name = "阿奇";   // 给属性赋值,相当于“装修”
myDog.Breed = "边牧";
myDog.Bark();          // 调用方法 -> 输出 "阿奇 说:汪汪!"Dog yourDog = new Dog();
yourDog.Name = "土豆";
yourDog.Breed = "柯基";
yourDog.Eat("狗粮");   // 输出 "土豆 正在吃狗粮"

核心关系:

  • 类是静态的定义,在编译时就已经确定。

  • 对象是动态的实例,在程序运行时被创建出来。

  • 一个类可以创建无数个对象,每个对象都有自己的状态(属性值)。

2.2 接口和类

这是一个容易混淆但至关重要的概念。它们不是对立的,而是互补的。

  1. 类 - 员工
  • 是什么:类是一个具体的实现者。它定义了事物是什么以及它如何做事

  • 生活比喻:一个具体的员工,比如张三。他有具体的技能,能实际完成工作。

// 一个具体的“数据库日志”实现者
public class DatabaseLogger : ILogger // 实现了 ILogger 接口
{public void Log(string message){// 他知道如何把消息记录到数据库Console.WriteLine($"将消息 '{message}' 写入数据库...");// ... 实际的数据库操作代码}
}
  1. 接口 - 契约/标准
  • 是什么:接口是一份契约、一个标准。它只规定了实现者必须做什么,但完全不关心具体怎么做

  • 关键字:interface

  • 生活比喻职位描述(JD)。上面写着“我们需要一个会写代码的人”。它不关心你是张三还是李四,只要你能写代码就行。这份JD就是接口。

  • 代码中:接口只包含方法、属性、事件或索引器的签名,没有任何实现

// 这是一个“日志记录器”的契约/标准
public interface ILogger
{// 只定义了“必须有一个Log方法,接收一个string参数”// 没有大括号 {} 实现体!void Log(string message);
}
  1. 实现接口:员工满足契约
    一个类可以实现一个或多个接口,这意味着它签署了这份契约,承诺提供接口中定义的所有功能。
// FileLogger 签署了 ILogger 契约,承诺会实现 Log 方法
public class FileLogger : ILogger // 使用 ‘:‘ 表示实现接口
{public void Log(string message){// 他用自己方式实现:写入文件Console.WriteLine($"将消息 '{message}' 写入文件...");// ... 实际的文件操作代码}
}// 甚至可以有一个控制台日志器
public class ConsoleLogger : ILogger
{public void Log(string message){// 他用另一种方式实现:打印到控制台Console.WriteLine($"日志输出: {message}");}
}
  1. 为什么需要接口?—— 松耦合与多态
    接口的核心威力在于它让代码极度灵活和可扩展。

想象一个业务场景:OrderService(订单服务)需要记录日志。

没有接口的糟糕写法(紧耦合):

public class OrderService
{// 直接依赖一个具体的实现private DatabaseLogger _logger = new DatabaseLogger();public void ProcessOrder(){_logger.Log("开始处理订单..."); // 永远只能用DatabaseLogger}
}

如果想换成文件日志,必须修改 OrderService 的代码。

使用接口的强大写法(松耦合):

public class OrderService
{// 只依赖一个抽象的契约,而不是具体的实现private readonly ILogger _logger;// 通过构造函数注入,告诉我你需要哪种日志器,但我不管具体是哪种public OrderService(ILogger logger){_logger = logger;}public void ProcessOrder(){_logger.Log("开始处理订单..."); // 神奇之处:这里不需要关心是哪个日志器}
}// 在程序入口处,我们决定用哪种具体的实现
var service = new OrderService(new FileLogger()); // 想用文件日志?注入它
// var service = new OrderService(new ConsoleLogger()); // 想用控制台?换这个
// var service = new OrderService(new DatabaseLogger()); // 想用数据库?再换这个
service.ProcessOrder();

总结接口的好处:

  • 定义标准:让多个类拥有统一的行为方式。

  • 实现多态:允许不同的类对同一方法有不同的实现。OrderService 可以应对任何实现了 ILogger 的类。

  • 松耦合:使代码模块之间不直接依赖具体实现,而是依赖抽象。这使得系统更灵活、更易测试(测试时可以注入一个“模拟”的日志器)和更易扩展(未来增加新的日志类型,如 EmailLogger,完全不需要修改 OrderService)。


2.3 访问修饰符

访问修饰符决定了类、方法、属性等成员的可见性和可访问性。它实现了OOP的封装特性,就像给房子装上了不同权限的门。

修饰符权限范围生活比喻代码示例
public无限制。任何地方的代码都可以访问。房子的前门,任何人都可以进来。public string Name;
private最严格。只有同一个类内部的代码可以访问。**卧室的私人抽屉,**只有你自己能打开。private string _secretCode;
protected家族权限。本类内部和所有派生类(子类) 中可以访问。家族的祖传密室,你和你的后代都可以进,外人不行。protected inheritanceKey;
internal项目/程序集权限。在同一个项目(程序集)内部可以访问,对外部项目不可见。公司办公室门禁,只有本公司员工能刷开,外面的人不行。internal EmployeeId;
protected internalprotected 或 internal。只要是本程序集内部,或者是派生类(即使在其他程序集),都可以访问。家族公司权限:要么你是家族成员(子类),要么你是公司员工(同程序集),二者满足其一即可进入。protected internal Fund;

为什么需要访问修饰符?—— 封装与安全

  1. 隐藏复杂性:只暴露必要的部分(public 方法),隐藏内部复杂的实现细节(private 字段和方法)。使用者只需要知道怎么用,不需要知道为什么能这么用。

  2. 防止误操作:将重要的数据字段设为 private,然后通过 public 的属性(Property)来控制访问和验证逻辑,防止外部代码将其设置为无效值。


总结与关系

  • 类和对象是OOP的基础,类是蓝图,对象是实例。

  • 接口是OOP的灵魂,它定义了契约,实现了松耦合和多态,让程序变得灵活而强壮。

  • 访问修饰符是OOP的卫士,它通过封装保护了对象的内部状态,确保了代码的安全性和健壮性。


2.4 (OOP)三大特性:封装、继承、多态

面向对象的特性:封装、继承、多态

2.5 其他成员:索引器、运算符重载

C# 中的两个强大特性:索引器 和 运算符重载。
它们都能让你自定义的类用起来更像内置类型,更加直观和优雅。

2.5.1 索引器:让对象像数组一样访问

  1. 核心概念:什么是索引器?
  • 是什么:索引器允许你的对象能够像数组字典一样,使用 [ ] 符号来访问其内部的元素或数据。

  • 目的:提供一种更直观、更简洁的方式来访问对象内部封装的集合或数据。

  • 本质:索引器本质上是一个特殊的属性,它拥有 get 和 set 访问器,但其访问方式不是通过属性名,而是通过索引(可以是任何类型)。

  1. 生活比喻:智能储物柜
    想象一个智能储物柜,它有一排排的箱子。你不是通过属性(如 Locker1,Locker2)来访问每个箱子,而是通过箱子的编号来存取物品。
  • myLocker[101] = “书包”; // 把书包存进 101 号箱子

  • string item = myLocker[101]; // 从 101 号箱子取回物品

这个 [101] 就是索引器。储物柜对象内部管理着所有箱子,但对外只暴露这个简单的索引接口。

  1. 语法与实现
    索引器的声明类似于属性,但使用 this 关键字,并在方括号 [ ] 中定义参数。
public class StringArray
{// 内部实际存储数据的数组private string[] _array = new string[10];// 索引器定义// 返回值类型: string// 参数: int indexpublic string this[int index]{get{// 读取逻辑:检查索引范围if (index < 0 || index >= _array.Length)throw new IndexOutOfRangeException();return _array[index];}set{// 写入逻辑:检查索引范围if (index < 0 || index >= _array.Length)throw new IndexOutOfRangeException();_array[index] = value;}}
}
  1. 如何使用
// 创建对象
StringArray myArray = new StringArray();// 使用索引器赋值 (调用 set 访问器)
myArray[0] = "Hello";
myArray[1] = "World";// 使用索引器读取 (调用 get 访问器)
Console.WriteLine(myArray[0]); // 输出 "Hello"
Console.WriteLine(myArray[1]); // 输出 "World"// 尝试越界访问
// Console.WriteLine(myArray[100]); // 会抛出 IndexOutOfRangeException
  1. 高级用法
  • 不同类型索引:索引不一定是 int,可以是 string 或其他类型,常用于实现字典行为。
public class PersonCollection
{private Dictionary<string, Person> _people = new Dictionary<string, Person>();// 以字符串(如名字)作为索引public Person this[string name]{get { return _people[name]; }set { _people[name] = value; }}
}// 使用
var collection = new PersonCollection();
collection["Alice"] = new Person("Alice", 30);
Person p = collection["Alice"];
  • 多参数索引:例如,模拟一个二维表格或棋盘。
public class GameBoard
{private int[,] _board = new int[3, 3];public int this[int row, int column]{get { return _board[row, column]; }set { _board[row, column] = value; }}
}// 使用
var board = new GameBoard();
board[1, 2] = 5; // 在第 2 行,第 3 列放置一个棋子

总结索引器
它完美体现了封装的思想。类内部可以用任何复杂的数据结构(数组、列表、字典、数据库连接)来存储数据,但对外提供了极其简单统一的数组式访问接口。

2.5.2 运算符重载:让对象支持数学运算

  1. 核心概念:什么是运算符重载?
  • 是什么:允许你为你自定义的结构体定义诸如 +, -, ==, !=, <, > 等运算符的行为。

  • 目的:让你自定义的类型用起来像内置类型(如 int, double)一样自然,支持直观的数学或逻辑运算。

  • 本质:运算符重载实际上是一个特殊的静态方法

  1. 生活比喻:货币兑换
    你有人民币(MoneyRMB)和美元(MoneyUSD)两种对象。100 RMB + 50 USD 应该如何计算?
  • 直接相加是毫无意义的。

  • 但如果你定义了 MoneyRMB 和 MoneyUSD 之间的 + 运算符,让它自动按汇率进行转换再计算,这个操作就变得非常直观和有用。

  1. 语法与实现
    运算符重载使用 operator 关键字,并声明为 public static。
public class Vector2D
{public double X { get; set; }public double Y { get; set; }public Vector2D(double x, double y){X = x;Y = y;}// 重载加法运算符 ‘+’public static Vector2D operator +(Vector2D v1, Vector2D v2){return new Vector2D(v1.X + v2.X, v1.Y + v2.Y);}// 重载减法运算符 ‘-’public static Vector2D operator -(Vector2D v1, Vector2D v2){return new Vector2D(v1.X - v2.X, v1.Y - v2.Y);}// 重载一元取反运算符 ‘-’public static Vector2D operator -(Vector2D v){return new Vector2D(-v.X, -v.Y);}
}
  1. 如何使用
Vector2D point1 = new Vector2D(1.0, 2.0);
Vector2D point2 = new Vector2D(3.0, 4.0);// 使用重载的 ‘+’ 运算符
Vector2D result1 = point1 + point2; // result1.X = 4.0, result1.Y = 6.0
Console.WriteLine($"({result1.X}, {result1.Y})"); // 输出 (4, 6)// 使用重载的 ‘-’ 运算符
Vector2D result2 = point1 - point2; // result2.X = -2.0, result2.Y = -2.0// 使用重载的一元 ‘-’ 运算符
Vector2D result3 = -point1; // result3.X = -1.0, result3.Y = -2.0
  1. 重载关系运算符(==, !=, <, > 等)

重载关系运算符通常需要成对重载(如重载 == 就必须重载 !=),并且最好同时重写 Equals() 和 GetHashCode() 方法,以保持逻辑一致性。

public class Vector2D
{// ... 之前的代码 ...// 重载 ‘==’ 运算符public static bool operator ==(Vector2D v1, Vector2D v2){// 处理 null 情况if (ReferenceEquals(v1, v2)) return true;if (v1 is null || v2 is null) return false;// 定义相等的逻辑:X 和 Y 都相等return v1.X == v2.X && v1.Y == v2.Y;}// 重载 ‘!=’ 运算符 (必须与 ‘==’ 逻辑相反)public static bool operator !=(Vector2D v1, Vector2D v2){return !(v1 == v2);}// 重写 Equals 方法,保持与 ‘==’ 逻辑一致public override bool Equals(object obj){if (obj is Vector2D other){return this == other; // 调用上面重载的 ‘==’ 运算符}return false;}// 重写 GetHashCode,如果两个对象相等,它们的哈希码也必须相等public override int GetHashCode(){return HashCode.Combine(X, Y);}
}
  1. 可重载的运算符
类别运算符备注
算术运算符+, -, *, /, %
递增/递减++, –
位运算符&, ,^,~,<<,>>
关系运算符==, !=, <, >, <=, >=必须成对重载
true/falsetrue, false极少使用

不可重载的运算符:.(成员访问)、()(调用)、new(对象创建)、&&, ||(条件逻辑,但它们会通过 & 和 | 来计算)、=(赋值)等。

总结与最佳实践

特性索引器运算符重载
目的让对象像数组/集合一样访问让对象像基本数值类型一样运算
核心语法public T this[P index] { get; set; }public static T operator +(T a, T b) { … }
适用场景自定义集合类、封装了内部数组/字典的类数学对象(向量、矩阵、复数)、物理量(长度、重量)、货币等
优点简化访问,隐藏内部数据结构的复杂性代码直观,更符合数学和物理直觉
注意事项确保索引有效性检查,避免抛出令人困惑的异常谨慎使用,确保运算逻辑对使用者来说显而易见。切忌滥用,例如重载 + 来表示不相关的操作(如合并两个订单)会大大降低代码可读性。始终成对重载关系运算符并重写 Equals/GetHashCode。

3. 异常处理

.NET异常处理


文章转载自:

http://wBZd7UZv.fstdf.cn
http://G6JtSY7X.fstdf.cn
http://4TmBbXwA.fstdf.cn
http://1p6uDBYY.fstdf.cn
http://CgeImsxs.fstdf.cn
http://qpxDGYt2.fstdf.cn
http://Fu8z29XI.fstdf.cn
http://Aac958Jn.fstdf.cn
http://xvFn7M7q.fstdf.cn
http://O0YqMWqG.fstdf.cn
http://lFH2HWJx.fstdf.cn
http://WfJ595Tb.fstdf.cn
http://RsRrrWj1.fstdf.cn
http://eE3Qzceq.fstdf.cn
http://1Y9E8IQA.fstdf.cn
http://qrIGwncz.fstdf.cn
http://8ajQaOVV.fstdf.cn
http://4IcnXgAN.fstdf.cn
http://vDaSSfOb.fstdf.cn
http://mBGa83wb.fstdf.cn
http://bywKpqlZ.fstdf.cn
http://iruLJBg1.fstdf.cn
http://ouceIbc6.fstdf.cn
http://dVsqN7YZ.fstdf.cn
http://835coY1H.fstdf.cn
http://vjbyOVKr.fstdf.cn
http://bi9sQuoE.fstdf.cn
http://qy6OObsn.fstdf.cn
http://oB97igyA.fstdf.cn
http://Hbgsz5fA.fstdf.cn
http://www.dtcms.com/a/382278.html

相关文章:

  • Python核心技术开发指南(061)——初始化方法__init__
  • 用 Go 采集服务器资源指标:从原理到实践
  • MySQL-day2_02
  • 基于springboot+vue开发的会议预约管理系统【50906】
  • 【Ubuntu】sudo apt update出现E :仓库***没有Release文件
  • JavaWeb--day3--AjaxElement路由打包部署
  • 阿里云国际代理:怎么保障数据库在凭据变更过程中的安全与稳定?
  • 关于子空间流形的认识
  • SQL注入漏洞手动测试详细过程
  • 【Linux】gcc/g++工具篇
  • libxl写到xls
  • 关键点(c++,Linux)
  • IO进程——进程引入、进程函数接口
  • Java 面向对象设计的六大原则
  • 今日分享:C++ deque与priority_queue
  • Vue3 通过json配置生成查询表单
  • spring 声明式事务
  • [硬件电路-190]:三极管的电流放大特性看男女关系3:过渡的投入,输出进入不安全区、疲惫期,反而双方系统造成伤害
  • json文件转excel
  • ros2获取topic信息解析
  • C++中的贪心算法
  • 【Selenium】Selenium 测试失败排查:一次元素定位超时的完整解决之旅
  • Selenium 使用指南
  • 【Python 入门】(2)Python 语言基础(变量)
  • XSS攻击1----(XSS介绍)
  • 【LeetCode 每日一题】3446. 按对角线进行矩阵排序——(解法一)分组 - 排序 - 重建
  • 【亲测有效】解决 “Batch script contains DOS line breaks (\r\n)” 报错
  • 集值优化问题:理论、应用与前沿进展
  • 17、逻辑回归与分类评估 - 从连续到离散的智能判断
  • AMD KFD的BO设计分析系列3-1: GTT的实现分析