值类型和引用类型的区别
区别 | 值类型 | 引用类型 |
---|
存储方式 | 直接存储值 | 存储对值的引用 |
内存位置 | 栈(Stack) | 堆(Heap) |
复制行为 | 复制值本身 | 复制引用(指向同一对象) |
默认值 | 例如:int 默认值为 0 | 默认为 null |
示例类型 | int , bool , struct | string , object , array |
字符串常用方法
方法 | 描述 | 示例 |
---|
Length | 获取字符串长度 | string s = "abc"; s.Length |
Substring | 提取子字符串 | s.Substring(1, 2) 返回"bc" |
Contains | 判断是否包含子字符串 | s.Contains("ab") → true |
Replace | 替换字符串 | s.Replace("a", "A") |
Split | 分割字符串 | "a,b,c".Split(',') |
Trim | 去除首尾空白字符 | " abc ".Trim() → "abc" |
引用类型和值类型内存分配对比
特性 | 引用类型(如class ) | 值类型(如struct ) |
---|
存储位置 | 堆(Heap) | 栈(Stack)或对象内 |
复制方式 | 复制引用(指向同一对象) | 复制值(创建独立副本) |
空值支持 | 可赋值null | 不可赋值null (除非是可空类型) |
性能 | 堆分配 / 回收开销大 | 栈分配 / 回收快 |
结构体与类(class)的区别
特性 | 结构体(struct) | 类(class) |
---|
类型 | 值类型 | 引用类型 |
继承 | 不能继承 / 被继承 | 可继承、实现接口 |
默认构造函数 | 自动生成,不可自定义 | 可自定义构造函数 |
内存效率 | 栈分配,适合高频使用场景 | 堆分配,适合复杂对象 |
访问修饰符
修饰符 | 访问权限描述 |
---|
public | 无访问限制 |
private | 仅在定义类型内部可访问 |
protected | 在定义类型及其派生类中可访问 |
internal | 在当前程序集(项目)内可访问 |
protected internal | 同时满足 protected 和 internal |
函数、结构体、类、方法、继承、接口核心区别总结
概念 | 类型 | 继承规则 | 内存分配 | 适用场景 |
---|
函数 | 静态方法 | 无 | 方法区 | 工具类、纯计算逻辑 |
结构体 | 值类型 | 不可继承,可实现接口 | 栈或对象内 | 轻量数据(坐标、时间) |
类 | 引用类型 | 单继承,支持多接口 | 堆 | 复杂对象(用户、订单) |
方法 | 类的成员 | 可重写、重载 | 随对象或类型 | 对象行为的具体实现 |
继承 | 类的关系 | 单继承(每个类一个父类) | 共享父类成员 | 代码复用、多态 |
接口 | 契约 | 可多实现 | 无(仅定义规范) | 定义行为、解耦组件 |
Random类、DateTime类、String类
类 | 类型 | 核心特性 |
---|
Random | 引用类型 | 伪随机数生成器,需注意种子和线程安全问题。 |
DateTime | 值类型 | 不可变,存储为 ticks,支持时区转换和格式化。 |
String | 引用类型 | 不可变,支持丰富操作,注意性能优化(如 StringBuilder 和插值)。 |
C# 中常用字符串(string
)方法
方法名称 | 说明 | 示例代码 | 执行结果 |
---|
Length (属性) | 获取字符串长度 | string s = "Hello"; int len = s.Length; | 5 |
ToUpper() | 转换为大写字母 | string s = "Hello"; string res = s.ToUpper(); | "HELLO" |
ToLower() | 转换为小写字母 | string s = "HELLO"; string res = s.ToLower(); | "hello" |
Trim() | 移除首尾空白字符 | string s = " Hello "; string res = s.Trim(); | "Hello" |
TrimStart() | 移除开头空白字符 | string s = " Hello"; string res = s.TrimStart(); | "Hello" |
TrimEnd() | 移除结尾空白字符 | string s = "Hello "; string res = s.TrimEnd(); | "Hello" |
Contains(string) | 判断是否包含指定子串 | string s = "Hello World"; bool res = s.Contains("World"); | true |
StartsWith(string) | 判断是否以指定子串开头 | string s = "Hello"; bool res = s.StartsWith("He"); | true |
EndsWith(string) | 判断是否以指定子串结尾 | string s = "Hello"; bool res = s.EndsWith("llo"); | true |
IndexOf(char) | 查找字符首次出现的索引(-1 表示未找到) | string s = "Hello"; int res = s.IndexOf('l'); | 2 |
LastIndexOf(char) | 查找字符最后出现的索引 | string s = "Hello"; int res = s.LastIndexOf('l'); | 3 |
Substring(int, int) | 从指定索引截取指定长度的子串 | string s = "Hello World"; string res = s.Substring(6, 5); | "World" |
Replace(string, string) | 替换指定子串为新字符串 | string s = "Hello"; string res = s.Replace("l", "x"); | "Hexxo" |
Split(char[]) | 按指定字符分割为字符串数组 | string s = "Apple,Banana,Orange"; string[] res = s.Split(','); | ["Apple", "Banana", "Orange"] |
Join(string, string[]) | 将字符串数组拼接为一个字符串 | string[] arr = { "A", "B", "C" }; string res = string.Join("-", arr); | "A-B-C" |
IsNullOrEmpty(string) | 判断字符串是否为null 或空串 | bool res1 = string.IsNullOrEmpty(""); bool res2 = string.IsNullOrEmpty(null); | true, true |
IsNullOrWhiteSpace(string) | 判断是否为null 、空串或仅含空白 | bool res = string.IsNullOrWhiteSpace(" "); | true |
Insert(int, string) | 在指定索引插入子串 | string s = "Hello"; string res = s.Insert(5, " World"); | "Hello World" |
Remove(int, int) | 从指定索引移除指定长度的字符 | string s = "Hello World"; string res = s.Remove(5, 1); | |
LINQ(Language Integrated Query)常用方法
方法类别 | 方法名称 | 说明 | 示例代码 | 执行结果(示例数据) |
---|
筛选 | Where | 根据条件 | | |
筛选满足条件的元素 | var adults = people.Where(p => p.Age >= 18); | 年龄≥18 的所有人 | | |
投影 | Select | 将元素转换为新形式(提取 / 转换字段) | var names = people.Select(p => p.Name); | 所有人的姓名集合(字符串数组) |
| SelectMany | 展平集合的集合(如嵌套列表) | var allRoles = departments.SelectMany(d => d.Employees.Select(e => e.Role)); | 所有部门员工的角色(一维集合) |
排序 | OrderBy | 按指定字段升序排序 | var sorted = people.OrderBy(p => p.Age); | 按年龄从小到大排序的人员 |
| OrderByDescending | 按指定字段降序排序 | var sorted = people.OrderByDescending(p => p.Salary); | 按薪资从高到低排序的人员 |
| ThenBy | 主排序后进行二次升序排序 | var sorted = people.OrderBy(p => p.Department).ThenBy(p => p.Name); | 先按部门排序,同部门内按姓名排序 |
聚合 | Count | 计算元素数量 | int studentCount = students.Count(s => s.Grade == "A"); | 成绩为 "A" 的学生数量 |
| Sum | 计算数值总和 | decimal total = orders.Sum(o => o.Amount); | 所有订单的总金额 |
| Average | 计算平均值 | double avgAge = people.Average(p => p.Age); | 所有人的平均年龄 |
| Max | 获取最大值 | int maxScore = scores.Max(); | 分数集合中的最高分 |
| Min | 获取最小值 | decimal minPrice = products.Min(p => p.Price); | 产品中的最低价格 |
| First | 获取第一个元素(无匹配时抛异常) | var first = people.First(p => p.IsActive); | 第一个活跃状态的人 |
| FirstOrDefault | 获取第一个元素(无匹配时返回默认值) | var first = people.FirstOrDefault(p => p.Role == "Admin"); | 第一个管理员(无则返回null ) |
集合操作 | Distinct | 去除重复元素 | var uniqueCities = people.Select(p => p.City).Distinct(); | 去重后的城市列表 |
| Union | 合并两个集合并去重 | var all = list1.Union(list2); | 两个列表的并集(无重复) |
| Intersect | 取两个集合的交集 | var common = list1.Intersect(list2); | 两个列表共有的元素 |
| Except | 取两个集合的差集(存在于第一个但不在第二个) | var diff = list1.Except(list2); | 仅在 list1 中存在的元素 |
分组 | GroupBy | 按指定字段分组 | var groups = people.GroupBy(p => p.Department); | 按部门分组的人员集合(键为部门,值为人员列表) |
连接 | Join | 类似 SQL 的内连接(基于键匹配两个集合) | var joined = orders.Join(users, o => o.UserId, u => u.Id, (o, u) => new { o.OrderId, u.Name }); | 订单与用户匹配的结果(含订单 ID 和用户名) |
限制 | Take | 获取前 N 个元素 | var top3 = products.OrderByDescending(p => p.Sales).Take(3); | 销量前三的产品 |
| Skip | 跳过前 N 个元素 | var page2 = list.Skip(10).Take(10); | 列表中第 11-20 个元素(分页场景) |
判断 | Any | 判断是否存在满足条件的元素 | bool hasAdmins = people.Any(p => p.Role == "Admin"); | 是否存在管理员(true /false ) |
| All | 判断所有元素是否都满足条件 | bool allPassed = students.All(s => s.Score >= 60); | 是否所有学生都及格(true /false ) |
泛型集合 vs 非泛型集合
特性 | 泛型集合(如List<T> ) | 非泛型集合(如ArrayList ) |
---|
类型安全 | 编译时检查,仅允许T 类型元素 | 存储object ,允许任意类型(不安全) |
性能 | 无装箱 / 拆箱,效率高 | 频繁装箱 / 拆箱,性能损耗大 |
代码可读性 | 明确指定类型,可读性强 | 需强制类型转换,易出错 |
适用场景 | 几乎所有场景,推荐优先使用 | 兼容旧代码,不推荐新开发使用 |
动态数组 vs 普通数组
特性 | 普通数组(T[] ) | 动态数组(List<T> ) |
---|
长度固定性 | 长度必须在创建时指定,不可变 | 长度随元素增减自动调整 |
初始化方式 | int[] arr = new int[5]; | List<int> list = new List<int>(); |
元素访问 | 通过索引直接访问(如 arr[0] ) | 同普通数组(如 list[0] ) |
动态扩容 | 需手动创建新数组并复制元素 | 自动扩容,无需手动处理 |
常用方法 | 仅支持 Length 、Array.Copy 等静态方法 | 支持 Add 、Remove 、Sort 等丰富方法 |
适用场景 | 长度已知且固定的场景 | 长度不确定或需频繁增删元素的场景 |
性能对比
方案 | 装箱开销 | 类型安全 | 性能(相对) |
---|
List<object> | 有 | 否 | 低 |
List<dynamic> | 无 | 否 | 中 |
自定义类 / 结构体 | 无 | 是 | 高 |
Dictionary<string, object> | 有 | 否 | 中 |
ExpandoObject | 无 | 否 | 中低 |
数组
类型 | 语法 | 特点 |
---|
一维数组 | int[] arr; | 元素连续存储,固定长度 |
多维数组 | int[,] matrix; | 矩形结构,每维长度固定 |
交错数组 | int[][] jagged; | 数组的数组,子数组长度可变 |
参数数组 | params int[] numbers | 方法接受可变数量的参数 |
方法关键字,ref、out、in、params
关键字 | 核心特性 | 参数初始化要求 | 适用场景 |
---|
in | 只读引用传递(不可修改) | 必须初始化 | 传递大型值类型,避免复制且禁止修改 |
ref | 可读写引用传递 | 必须初始化 | 需要修改原始变量(输入 + 输出) |
out | 输出引用传递(必须赋值) | 无需初始化,但方法内必须赋值 | 多返回值场景(如解析、验证) |
params | 可变数量参数 | 无(自动包装为数组) | 参数数量不确定的场景(如动态传参求和) |
Lambda表达式的常见用法
类型 | 语法格式 | 示例代码 | 说明 |
---|
无参数 | () => 表达式 | () => Console.WriteLine("Hello") | 无输入参数,执行单一表达式或语句块 |
单参数 | 参数 => 表达式 | x => x * 2 | 单个参数可省略括号,表达式返回计算结果 |
多参数 | (参数1, 参数2) => 表达式 | (a, b) => a + b | 多个参数需用括号包裹,用逗号分隔 |
语句块 | 参数 => { 语句; } | n => { if (n > 0) return "正"; else return "负"; } | 复杂逻辑需用{} 包裹,需显式使用return 返回值 |
委托匹配 | 与委托签名一致 | Func<int, bool> isEven = x => x % 2 == 0; | 匹配Func<int, bool> 委托(输入 int,返回 bool) |
事件处理 | 简化事件订阅 | button.Click += (s, e) => Console.WriteLine("Clicked"); | 替代传统的事件处理方法,简化代码 |
LINQ 筛选 | 结合Where 方法 | var adults = people.Where(p => p.Age >= 18); | 在 LINQ 中用于定义筛选条件,p 代表集合中的每个元素 |
LINQ 投影 | 结合Select 方法 | var names = people.Select(p => p.Name); | 提取元素的特定属性,转换为新的序列 |
排序条件 | 结合OrderBy 方法 | var sorted = numbers.OrderBy(n => n); | 定义排序依据,此处按元素本身升序排序 |
匿名类型创建 | 生成匿名对象 | people.Select(p => new { p.Name, AgeGroup = p.Age / 10 * 10 }) | 在 LINQ 中创建匿名类型,包含指定字段(如Name 和AgeGroup ) |
闭包捕获变量 | 访问外部变量 | int threshold = 10; var filtered = list.Where(x => x > threshold); | 可访问 Lambda 表达式外部的变量(threshold ),形成闭包 |
异步 Lambda | 结合async/await | async () => await HttpClient.GetAsync("https://example.com") | 用async 修饰,内部可使用await ,返回Task 或Task<T> |
关键特性说明:
简洁性:相比匿名方法,语法更简洁,省略了delegate
关键字和参数类型(编译器自动推断)。
类型推断:参数类型通常可省略,编译器会根据上下文(如委托类型、LINQ 方法)自动推断。
不可变性:Lambda 表达式本身是匿名函数,无法直接调用,需赋值给委托类型(如Func
、Action
)或作为方法参数传递。
闭包特性:能捕获并访问外部作用域的变量,变量的生命周期会被延长至 Lambda 表达式使用完毕。
适用场景:主要用于简化委托调用、事件处理、LINQ 查询、异步操作等场景,减少代码冗余。
C#Array
1. 核心静态方法(Array.XXX
)
静态方法需通过Array
类直接调用,主要用于数组查询、判断、遍历等,参数常包含 “回调函数”(定义查询条件)。
方法 | 作用 | 关键参数 | 示例场景 |
---|
Find | 从前向后查找第一个满足条件的元素 | 数组 + 回调函数(返回bool ,表示元素是否符合条件) | 查找第一个不满 18 岁的年龄(Array.Find(ages, FindSamll18) ) |
FindLast | 从后向前查找第一个满足条件的元素 | 同Find | 查找最后一个能被 3 和 5 整除的数(Array.FindLast(ages, Find35) ) |
FindIndex | 从前向后查找第一个满足条件的元素的索引 | 同Find | 查找第一个能被 3 和 5 整除的数的索引(Array.FindIndex(ages, Find35) ) |
FindLastIndex | 从后向前查找第一个满足条件的元素的索引 | 同Find | 查找最后一个能被 3 和 5 整除的数的索引(Array.FindLastIndex(ages, Find35) ) |
TrueForAll | 判断数组所有元素是否都满足条件(全满足返回true ) | 数组 + 回调函数 | 判断所有数字是否都是偶数(Array.TrueForAll(nums, FindEven) ) |
Exists | 判断数组至少有一个元素满足条件(有一个满足返回true ) | 数组 + 回调函数 | 判断是否存在偶数(Array.Exists(nums, FindEven) ) |
ForEach | 遍历数组,对每个元素执行指定操作(替代for /foreach 的专用遍历) | 数组 + 回调函数(无返回值,执行操作) | 遍历数组并对每个元素 + 1 输出(Array.ForEach(nums, Each) ) |
2. 实例方法(数组对象.XXX)
实例方法通过数组对象调用,主要用于数组复制、元素操作、属性查询等。
方法 | 作用 | 示例 |
---|
CopyTo | 将当前数组元素复制到目标数组的指定位置 | str1.CopyTo(str2, 1) (将str1 从str2[1] 开始复制) |
GetLength | 获取多维数组指定维度的长度(一维数组等效于Length ) | str1.GetLength(0) (返回一维数组str1 的长度) |
GetValue /SetValue | 获取 / 设置指定索引的元素值 | str1.GetValue(0) (获取str1[0] );str1.SetValue("郑爽", 1) (设置str1[1] ) |
Contains | 判断数组是否包含指定元素(需引入System.Linq ) | str1.Contains("李云迪") (判断是否包含 “李云迪”) |
c#泛型集合(ArrayList和List、Dictionary的对比)
List<T> 集合
操作 | 代码示例 | 说明 |
---|
添加元素 | list.Add(100); | 在末尾添加单个元素。 |
批量添加 | list.AddRange(new[] {1, 2, 3}); | 添加集合中的所有元素。 |
插入元素 | list.Insert(1, "apple"); | 在指定索引处插入元素。 |
访问元素 | string item = list[0]; | 通过索引访问元素(索引从 0 开始)。 |
修改元素 | list[0] = "banana"; | 通过索引修改元素值。 |
删除元素 | list.Remove("apple"); | 删除第一个匹配的元素。 |
删除指定位置 | list.RemoveAt(0); | 删除指定索引的元素。 |
判断元素存在 | bool exists = list.Contains("apple"); | 检查列表是否包含指定元素。 |
获取元素索引 | int index = list.IndexOf("apple"); | 返回元素的第一个索引(不存在返回 -1)。 |
排序 | list.Sort(); | 对列表进行升序排序(元素需实现 IComparable )。 |
反转顺序 | list.Reverse(); | 反转列表元素的顺序。 |
清空列表 | list.Clear(); | 移除所有元素。 |
获取元素数量 | int count = list.Count; | 返回列表中的元素个数。 |
高阶函数(Lambda 表达式)
方法 | 作用 | 示例 |
---|
Find() | 查找第一个符合条件的元素。 | int evenNum = list.Find(x => x % 2 == 0); |
FindAll() | 查找所有符合条件的元素,返回新列表。 | List<int> evens = list.FindAll(x => x % 2 == 0); |
FindIndex() | 查找第一个符合条件的元素的索引。 | int index = list.FindIndex(x => x > 10); |
Any() | 判断是否存在符合条件的元素(返回 bool )。 | bool hasEven = list.Any(x => x % 2 == 0); |
All() | 判断所有元素是否都符合条件。 | bool allPositive = list.All(x => x > 0); |
Where() | 筛选符合条件的元素(返回 IEnumerable<T> )。 | var filtered = list.Where(x => x < 100); |
ForEach() | 对每个元素执行操作。 | list.ForEach(x => Console.WriteLine(x)); |
Dictionary<TKey, TValue> 字典
操作 | 代码示例 | 说明 |
---|
添加键值对 | dict.Add("apple", 1); | 添加键值对(键不存在时)。 |
通过键访问值 | int value = dict["apple"]; | 通过键获取值(键不存在时抛出异常)。 |
通过键设置值 | dict["apple"] = 100; | 修改已存在键对应的值。 |
安全获取值 | bool found = dict.TryGetValue("apple", out int value); | 尝试获取值,避免异常。 |
判断键是否存在 | bool hasKey = dict.ContainsKey("apple"); | 检查字典是否包含指定键。 |
判断值是否存在 | bool hasValue = dict.ContainsValue(1); | 检查字典是否包含指定值。 |
删除键值对 | dict.Remove("apple"); | 删除指定键对应的元素。 |
清空字典 | dict.Clear(); | 移除所有键值对。 |
获取所有键 | var keys = dict.Keys; | 返回所有键的集合(类型:Dictionary<TKey, TValue>.KeyCollection )。 |
获取所有值 | var values = dict.Values; | 返回所有值的集合(类型:Dictionary<TKey, TValue>.ValueCollection )。 |
获取元素数量 | int count = dict.Count; | 返回字典中键值对的数量。 |
集合ArryList、List、Hashtable、SortedList、Dictionary等总结
集合类型 | 类型是否固定 | 长度是否固定 | 核心特性 | 长度表示 | 典型用途 |
---|
数组(Array) | 固定 | 固定 | 连续内存,索引访问快 | Length | 存储固定长度、同类型数据 |
ArrayList | 不固定 | 不固定 | 动态数组,可存任意类型 | Count | 存储无类型限制的动态数据 |
List<T> | 固定(T ) | 不固定 | 泛型动态列表,类型安全 | Count | 存储同类型动态数据(推荐) |
Dictionary<TKey,TValue> | 固定 | 不固定 | 键值对,键唯一,查询快 | Count | 需通过键快速查找值的场景 |
Hashtable | 不固定 | 不固定 | 非泛型键值对,哈希查找 | Count | 兼容旧代码的键值对存储 |
SortedList | 键类型固定 | 不固定 | 键值对,自动按键排序 | Count | 需要排序的键值对场景 |
Stack | 不固定 | 不固定 | 后进先出(LIFO) | Count | 回溯、表达式求值等 |
Queue | 不固定 | 不固定 | 先进先出(FIFO) | Count | 消息队列、任务调度等 |
集合与数组的核心区别:
特性 | 数组(Array) | 集合(Collection) |
---|
类型限制 | 固定类型(object[] 除外) | 部分类型固定(如List<T> ),部分可存任意类型(如ArrayList ) |
长度特性 | 固定长度,创建后不可变 | 动态长度,可自动扩容 / 缩容 |
内存布局 | 连续内存块 | 非连续(多数集合) |
性能 | 访问速度快(直接索引) | 增删改效率高(避免数组扩容开销) |
装箱拆箱 | 无(值类型直接存储) | 非泛型集合有(如ArrayList 存储值类型时) |
访问修饰符
访问修饰符 / 范围 | 当前类 | 父类 | 实例对象 | 引用当前项目的项目子类 | 引用当前项目实例对象 | 同一程序集的非子类 | 不同程序集的子类 | 不同程序集的非子类 |
---|
public | √ | √ | √ | √ | √ | √ | √ | √ |
private | √ | × | × | × | × | × | × | × |
internal | √ | √ | √ | √ | √ | √ | × | × |
protected | √ | √ | × | √ | × | × | √ | × |
protected internal | √ | √ | × | √ | √ | √ | √ | × |
private protected | √ | × | × | √ (仅同一程序集) | × | × | × (不同程序集) | × |
c#正则表达式
核心类:
2. 常用元字符和语法
元字符 | 含义 | 示例 |
---|
. | 匹配任意单个字符(除换行符) | a.b 匹配 acb |
^ | 匹配字符串开头 | ^Hello 匹配以Hello 开头的字符串 |
$ | 匹配字符串结尾 | world$ 匹配以world 结尾的字符串 |
* | 匹配前面的元素 0 次或多次 | ab* 匹配 a 、ab 、abb 等 |
+ | 匹配前面的元素 1 次或多次 | ab+ 匹配 ab 、abb ,但不匹配 a |
? | 匹配前面的元素 0 次或 1 次 | ab? 匹配 a 或 ab |
{n} | 匹配前面的元素恰好 n 次 | a{3} 匹配 aaa |
{n,} | 匹配前面的元素至少 n 次 | a{2,} 匹配 aa 、aaa 等 |
{n,m} | 匹配前面的元素 n 到 m 次 | a{2,3} 匹配 aa 或 aaa |
[] | 匹配方括号内的任意一个字符 | [abc] 匹配 a 、b 或 c |
[^] | 匹配不在方括号内的任意字符 | [^abc] 匹配除 a 、b 、c 外的字符 |
| | 或运算,匹配左侧或右侧的模式 | a|b 匹配 a 或 b |
() | 分组,用于捕获子表达式或优先级 | (ab)+ 匹配 ab 、abab 等 |
3. 预定义字符类
字符类 | 等价于 | 含义 |
---|
\d | [0-9] | 匹配数字 |
\D | [^0-9] | 匹配非数字 |
\w | [a-zA-Z0-9_] | 匹配字母、数字或下划线 |
\W | [^a-zA-Z0-9_] | 匹配非字母、数字或下划线 |
\s | [ \t\n\r\f\v] | 匹配空白字符(空格、制表符等) |
\S | [^ \t\n\r\f\v] | 匹配非空白字符 |
常用方法
方法 | 描述 |
---|
IsMatch(input) | 检查输入是否匹配模式 |
Match(input) | 返回第一个匹配结果 |
Matches(input) | 返回所有匹配结果的集合 |
Replace(input, replacement) | 替换匹配的文本 |
Split(input) | 根据匹配结果分割字符串 |
场景 | 正则表达式模式 | 说明 |
---|
邮箱验证 | ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$ | 简单邮箱格式验证 |
身份证号验证 | ^\d{17}[\dXx]$ | 18 位身份证号(含 X 结尾) |
URL 验证 | ^https?://[^\s/$.?#].[^\s]*$ | 验证 HTTP/HTTPS URL |
数字验证 | ^-?\d+(\.\d+)?$ | 整数或小数 |
汉字验证 | ^[\u4e00-\u9fa5]+$ | 纯中文字符 |
c#接口与抽象类的对比
特性 | 接口 | 抽象类 |
---|
实例化 | 不能实例化 | 不能实例化 |
成员实现 | 所有成员无实现(纯规范) | 可以包含抽象成员(无实现)和非抽象成员(有实现) |
继承 / 实现方式 | 类 / 结构体通过: 实现,支持多实现 | 类通过: 继承,仅支持单继承 |
成员访问修饰符 | 默认 public,不能显式添加修饰符 | 可以有 public、protected 等修饰符 |
包含的成员类型 | 只能有属性、方法、索引器、事件(无字段) | 可以有字段、属性、方法、索引器、事件等 |
关系本质 | 表示 “具有某种能力”(has-a) | 表示 “是一种”(is-a) |
结构体支持 | 结构体可以实现接口 | 结构体不能继承抽象类(结构体是值类型) |
c#方法
以下是 C# 中各类方法的汇总表格,包含核心特性、修饰符、使用场景及示例:
方法类型 | 修饰符 / 关键字 | 核心特性 | 典型使用场景 | 简单示例代码 |
---|
实例方法 | 无(默认) | 属于类的实例,需通过对象调用;可访问实例成员和静态成员 | 操作对象的状态或行为(如Person.SayHello() ) | public void Introduce() { ... } |
静态方法 | static | 属于类本身,通过类名调用;只能访问静态成员;无this 指针 | 工具类、辅助方法(如Math.Max() ) | public static int Add(int a, int b) { ... } |
虚方法 | virtual (基类) | 基类中定义,允许派生类重写;有默认实现 | 需在派生类中灵活扩展的方法(如Animal.MakeSound() ) | public virtual void MakeSound() { ... } |
抽象方法 | abstract (仅抽象类中) | 无实现体;强制派生类重写;只能在抽象类中定义 | 定义基类模板(如Shape.CalculateArea() ) | public abstract double CalculateArea(); |
重写方法 | override | 派生类中重写基类的虚方法或抽象方法;实现多态 | 定制基类方法的具体行为(如Dog.MakeSound() ) | public override void MakeSound() { Console.WriteLine("Woof"); } |
密封方法 | sealed override | 阻止派生类进一步重写;需配合override 使用 | 保护核心方法逻辑不被修改 | public sealed override void MakeSound() { ... } |
扩展方法 | static (类)+ this (参数) | 为现有类型添加方法,无需修改原类型;定义在静态类中 | 增强系统类型功能(如为string 添加Reverse() ) | public static string Reverse(this string s) { ... } |
重载方法 | 无(同名不同参) | 同一类中方法名相同,参数列表(类型 / 数量 / 顺序)不同;编译时绑定 | 提供多参数组合的灵活调用(如Add(int) /Add(double) ) | public int Add(int a) { ... } public double Add(double a) { ... } |
异步方法 | async + Task /Task<T> | 非阻塞执行;使用await 标记异步操作;返回Task 或Task<T> | 网络请求、文件 IO 等耗时操作 | public async Task<string> DownloadAsync(string url) { ... } |
说明:
访问修饰符(public
/private
等)可应用于所有方法,控制访问范围。
方法的核心区别体现在所属范围(实例 / 类)、继承行为(可重写 / 密封)、调用方式(对象 / 类名 / 扩展)等维度。
表格中的 “示例代码” 为简化版,实际使用需结合类定义完整实现。
c#类
类类型 | 修饰符 | 核心特点 | 典型用途 |
---|
普通类 | 无 | 可实例化、可继承 | 大多数业务实体(如User 、Order ) |
静态类 | static | 不可实例化、仅含静态成员 | 工具类(如DateTimeHelper ) |
抽象类 | abstract | 不可实例化、含抽象成员 | 定义基类模板(如Shape 、Animal ) |
密封类 | sealed | 不可被继承 | 保护核心类(如string ) |
部分类 | partial | 拆分到多文件,编译时合并 | 大型类或自动生成代码 |
基类 / 派生类 | 无(用: ) | 继承关系,派生类扩展基类 | 代码复用与扩展(如Animal →Cat ) |