CSharp
文章平均质量分 63
曹牧
从牙牙学语到灵活运用,风风雨雨
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
C#:where 子句用于对泛型类型参数施加约束(Constraints)
访问成员:如果没有约束,泛型类型 T 被视为 System.Object,只能调用 ToString()、Equals()、GetType() 等 Object 成员。例如,where T : struct 结合接口调用时,CLR 可以使用 constrained. IL 指令直接调用值类型的方法,而不必将其装箱为 object。where T : struct 隐含了 T 有无参构造函数(所有值类型都有),因此不能同时写 where T : struct, new(),这会引发编译错误。原创 2026-11-05 16:05:54 · 262 阅读 · 0 评论 -
C# 泛型类 和 泛型结构体
协变与逆变:只有接口和委托支持协变(out T)和逆变(in T)。不变性 (Invariance):默认情况下,GenericBox<object> 和 GenericBox<string> 是完全不同的类型,即使 string 继承自 object,它们之间也不能直接隐式转换。如果数据大小超过 16 字节,或者需要频繁在方法间传递,优先使用类,因为结构体的拷贝开销会变大。如果追求高性能、不可变性且数据很小(如 Point<T>, Range<T>),使用结构体。原创 2026-11-05 15:56:42 · 475 阅读 · 0 评论 -
C#:The operation has timed out
LogManager.GetLogger().InfoEx("DoHmCdssHttpPost-url[" + url + "]失败/空结果, 耗时[" + stciadt.TotalMilliseconds + "]");LogManager.GetLogger().ErrorEx("DoHmCdssHttpPost 网络错误: " + we.Message);效果:对于 POST 请求,这能显著减少延迟,特别是在超时时间很短(如 1500ms)的场景下,这是解决“莫名超时”的关键技巧之一。原创 2026-10-29 15:02:50 · 342 阅读 · 0 评论 -
`regsvr32` 注册
如果不加 `%~dp0`,直接写 `regsvr32 my.ocx`,那系统找的是“当前工作目录”下的文件,一旦你从别的地方调用这个批处理,当前目录变了,就会报“找不到模块”。2. `"%~dp0"`:批处理里的特殊变量,表示“当前批处理文件所在的文件夹路径”,以 `\` 结尾。2. 32位控件在64位系统上:如果 `my.ocx` 是 32 位的,而系统是 64 位,直接用系统自带的 `regsvr32`(64位版本)会注册失败。`%~dp0` 会自动展开成这个批处理文件所在的完整路径(末尾带 `\`)原创 2026-10-22 10:17:49 · 165 阅读 · 0 评论 -
C#里引用ActiveX控件
注册失败排查:如果`regsvr32`注册失败,检查路径是否含空格未加引号、是否用了错误位数的命令提示符(32位控件要用`C:\Windows\SysWOW64\regsvr32.exe`注册)、以及控件依赖的MFC或C++运行时库(如`MFCxx.dll`、`MSVCRT`)是否缺失。2. 添加COM引用:在Visual Studio中,右键项目 → “添加” → “引用” → 切换到“COM”选项卡,在列表中找到对应的OCX组件(名称通常和文件名相关),勾选后点击“确定”。原创 2026-10-22 09:50:33 · 123 阅读 · 0 评论 -
C#:字符串占位符与值数量不一致
C#字符串占位符与值数量不一致,运行时会抛出 `FormatException`(提示“输入字符串的格式不正确”)或 `IndexOutOfRangeException`,这是由占位符索引和参数个数不匹配导致的。4. 花括号未转义:格式字符串中直接写 `{` 或 `}`(如 JSON 片段 `"{name:\"{0}\"}"`),会被误解析为占位符边界,导致格式错误。2. 占位符索引不连续或跳号:如 `{0} {2}` 传 3 个参数,`{2}` 本身合法,但若索引超过参数总数上限就会报错。原创 2026-10-19 16:59:45 · 178 阅读 · 0 评论 -
C#:空合并运算符
/ count = 0,避免 NullReferenceException。` 是空合并运算符。若左操作数不为 `null`,返回左操作数;否则返回右操作数(默认值)。// 3. 链式默认值(从左到右取第一个非null)可空值类型(`int?`)或引用类型提供兜底值。// 4. 结合?. 安全访问并提供默认值。// 1. 可空值类型转非空。// 2. 引用类型兜底。原创 2026-10-19 15:28:24 · 85 阅读 · 0 评论 -
VS: Visual Studio 里把未包含的文件加进项目2
如果包含后编译报“无法打开源文件”,多半不是没包含,而是头文件路径问题——`include "xxx.h"` 的搜索顺序是:当前.cpp 所在目录 → 附加包含目录 → 系统目录,需要确认头文件在这几个路径里。> 建议先用“显示所有文件 + 包含在项目中”这个组合,它对单个文件和整个文件夹都适用,操作最直观,不会像“添加现有项”那样留下文件位置变更的隐患。- 文件在磁盘上存在但项目里看不到,通常是“显示所有文件”没打开,或者文件被手动从项目里排除了(右键“从项目中排除”)。原创 2026-10-15 16:45:31 · 203 阅读 · 0 评论 -
C#:输入的字符串格式不正确
4. 检查 string.Format:需要输出花括号时用双写转义,`{{`表示`{`,`}}`表示`}`。3. 确认日期格式:用 DateTime.ParseExact 指定确切格式,如"yyyy-MM-dd"。2. 检查字符串是否为空:转换前先判断`string.IsNullOrEmpty(str)`。3. string.Format 问题:格式字符串里花括号没正确转义,占位符数量不对。2. 格式不匹配:比如字符串"abc"想转成数字,或者日期字符串格式不对。// 转换成功,使用 result。原创 2026-10-14 10:04:08 · 277 阅读 · 0 评论 -
C#:未被引用的函数
1. 使用“查找所有引用”:在代码编辑器中右键点击函数名,选择“查找所有引用”,或选中后按 `Shift+F12`,即可查看整个解决方案中所有引用该函数的位置。C#编译器默认不会对未被引用的函数报警告,所以这类代码通常能正常编译通过,但会影响代码整洁度,也可能藏着死代码或遗漏的逻辑。- 反射调用:通过反射方式调用的函数,即使代码中没有直接引用,静态分析工具也可能会误报为“未使用”,需人工判断后再清理。- 对于暂时保留但未被调用的函数,建议添加注释说明原因,避免后续维护时误删。🧹 查找未引用的函数。原创 2026-10-09 14:38:19 · 207 阅读 · 0 评论 -
C#:List获取第一个元素
注意:`First()`在序列为空或无匹配项时抛出`InvalidOperationException`,生产环境建议优先使用`FirstOrDefault()`并检查返回值。获取List第一个元素推荐使用LINQ的`First()`或`FirstOrDefault()`,需引入`System.Linq`命名空间。查找满足条件的首个元素,未找到时`First`抛异常,`FirstOrDefault`返回默认值。若列表为空,`First()`会抛出异常。// 推荐:安全获取,空列表时返回0。原创 2026-09-22 16:17:55 · 232 阅读 · 0 评论 -
C#:HashSet<T> 去重
HashSet<T> 底层基于哈希表实现,去重依赖 `GetHashCode()` 和 `Equals()` 两个方法。* 性能优化:`Add()` 返回 bool 值,直接利用返回值判断是否为新元素,避免额外调用 `Contains()` 造成二次哈希查找。// 构造函数直接去重。if (seenIds.Add(id)) // Add 返回 true 表示是新元素,false 表示已存在。3. 契约约束:若 `Equals()` 返回 true,`GetHashCode()` 必须返回相同值;原创 2026-09-18 15:34:14 · 316 阅读 · 0 评论 -
C#:24小时制时间
注意区分:`HH` 是 24 小时制的小时,`hh` 是 12 小时制的小时;`MM` 是月份,`mm` 才是分钟,别写混了。- 毫秒:`yyyy-MM-dd HH:mm:ss.fff`,如 `2026-09-15 14:30:00.123`- 完整日期时间:`yyyy-MM-dd HH:mm:ss`,如 `2026-09-15 14:30:00`- 不带秒:`yyyy-MM-dd HH:mm`,如 `2026-09-15 14:30`- 只要时间:`HH:mm:ss`,如 `14:30:00`原创 2026-09-15 14:26:20 · 193 阅读 · 0 评论 -
VS:项目管理
3. 找到包含 `Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}")` 且路径指向不存在文件的段落,以及 `GlobalSection(ProjectConfigurationPlatforms)` 中对应的配置项,将其删除。在 Visual Studio 中处理“不存在的项目”通常指两种情况:一是解决方案中引用了物理路径已丢失的项目(加载失败),二是项目中引用了不存在的程序集或 NuGet 包。2. 移除项目中未使用/无效的引用(NuGet 或 DLL)原创 2026-09-08 14:26:58 · 187 阅读 · 0 评论 -
C#:模态对话框
阻止自动关闭:若需在设置 `DialogResult` 前执行额外逻辑(如保存数据),可在 `FormClosing` 事件中检查 `DialogResult` 或通过 `e.Cancel = true` 拦截,但通常建议在按钮点击事件中先执行逻辑再设置 `DialogResult`。- 仅对模态窗体有效:如果窗体是通过 `Show()` 显示的,设置 `DialogResult` 不会关闭窗体,且调用者无法通过 `ShowDialog()` 接收返回值。// 设置结果并自动关闭窗体。原创 2026-09-08 11:09:41 · 243 阅读 · 0 评论 -
C#:窗体Topmost与获取输入焦点
2. 若需持续保持焦点(如锁屏软件),需配合 `Timer` 周期性调用 `SetForegroundWindow` 并检查 `GetForegroundWindow()` 是否为本窗口句柄。仅设置 `TopMost = true` 无法保证窗体获取键盘输入焦点。3. `TopMost` 仅控制 Z-order(显示层级),`SetForegroundWindow` 控制输入焦点,两者需配合使用。// 可选:确保内部控件也获得焦点(如TextBox)/// 调用此方法使窗体置顶并获取焦点。原创 2026-09-08 09:21:59 · 226 阅读 · 0 评论 -
C#:线程间操作无效,不是从创建控件线程访问
控件已经关闭或销毁后,`InvokeRequired` 可能还是 `true`,但此时再 `Invoke` 会抛 `ObjectDisposedException`。C#中“线程间操作无效,不是从创建控件线程访问”,原因就是 UI 控件只能在创建它的主线程上操作,从后台线程(比如 `Thread`、`Task.Run`)直接改控件属性,就会被系统拦下来。写法是先用 `InvokeRequired` 判断当前线程,再调用 `Invoke` 或 `BeginInvoke` 把委托交给主线程执行。原创 2026-09-03 15:48:47 · 348 阅读 · 0 评论 -
C#:文本文件读取
C#读取文本文件主要有三种方式:`File` 静态类、`StreamReader` 流式读取和 `FileStream` 字节流操作。2. 文件不存在:读取前建议用 `File.Exists()` 判断,或把代码放在 `try-catch` 里捕获 `FileNotFoundException`。3. 资源释放:所有流类(`StreamReader`、`FileStream`)用完必须关闭,否则文件会被锁定,推荐用 `using` 语句自动处理。记得用 `using` 语句自动释放资源。原创 2026-09-03 09:04:51 · 179 阅读 · 0 评论 -
C#:解析 JSON 出现中文乱码
C#解析 JSON 出现中文乱码,原因就是编码不一致:JSON 数据本身是 UTF-8 编码,而程序读取或发送时用了系统默认编码(如 GBK),导致。- HTTP 发送/接收 JSON 乱码:`Content-Type` 缺少 `charset=utf-8`,或发送内容没按 UTF-8 编码。- 读取 JSON 文件乱码:用 `StreamReader` 读取时没指定 UTF-8 编码。- 序列化/反序列化后乱码:用了 `Newtonsoft.Json`,但没有正确设置转义或编码。✅ 最常见的解决方案。原创 2026-09-03 08:59:53 · 219 阅读 · 0 评论 -
C#:RadioButton
ASP.NET Web Forms:通过设置 `GroupName` 属性为相同的值来创建一组互斥控件,例如两个按钮的 `GroupName` 都设为 "Options"。<RadioButton Content="选项 1" GroupName="MyGroup" IsChecked="True"/><RadioButton Content="选项 2" GroupName="MyGroup"/>- Checked:布尔值,指示控件是否被选中(True 表示选中,False 表示未选中)。原创 2026-09-02 13:44:05 · 181 阅读 · 0 评论 -
C#:重载窗体构造函数
必须确保在所有自定义构造函数中调用 `InitializeComponent()`,通常通过链式调用无参构造函数实现,以保证界面控件正确初始化。- 严禁在 `InitializeComponent()` 之前访问窗体上的控件(如 `textBox1.Text = "..."`),否则会抛出空引用异常,因为此时控件尚未创建。- 如果需要在界面初始化后执行逻辑,建议重写 `OnLoad` 方法或在构造函数末尾添加代码,而不是修改 `InitializeComponent` 内部实现。原创 2026-09-02 11:10:56 · 877 阅读 · 0 评论 -
C#与Java后台交互
使用 Spring Boot 框架,通过 `@RestController` 和 `@PostMapping` 接收请求,`@RequestBody` 会自动将 JSON 数组反序列化为 `List<T>`。C#与 Java 后台交互通常通过 HTTP 协议进行,标准做法是将 `List<T>` 序列化为 JSON 字符串发送,Java 后端使用 `@RequestBody` 接收并自动反序列化。- C#端必须设置 `Content-Type` 为 `application/json`。原创 2026-08-26 10:24:25 · 458 阅读 · 0 评论 -
C#:数组与列表的差异
C# 数组(Array)是的连续内存块,适合场景;泛型列表(List<T>)是的封装结构,适合场景。两者索引访问均为 O(1),但底层开销与内存行为差异显著。原创 2026-08-26 09:24:32 · 288 阅读 · 0 评论 -
C#:数组赋值
数值类型默认为 `0`,引用类型为 `null`,布尔类型为 `false`。// 使用 LINQ 生成序列 (需 using System.Linq;// 将所有元素填充为 -1。矩形数组(`[,]`)和交错数组(`[][]`)的赋值方式不同。// 修改第1行第2列。// 创建长度为 10 的整型数组,所有元素初始化为 0。// 显式指定类型(当需要隐式转换或明确类型时)// 交错数组 (数组的数组,每行长度可不同)// 若需自定义默认值(.NET 5+)// 矩形数组 (2行3列)原创 2026-08-26 09:11:36 · 346 阅读 · 0 评论 -
C#:`StringBuilder`类判空
在C#中,使用`StringBuilder`类时,可能想要在添加字符串或执行其他操作之前检查`StringBuilder`是否为空。`StringBuilder`本身不直接提供一个“判空”的方法,因为它本质上是一个可变的字符串容器,不像`string`那样有一个固定的长度或内容。也可以先将`StringBuilder`的内容转换为字符串,然后检查该字符串的长度。最直接的方法是检查`StringBuilder`的`Length`属性。如果长度为0,那么可以认为它是“空的”。原创 2026-08-19 17:00:05 · 136 阅读 · 0 评论 -
C#:数字的定义和表示方式
/ 或者 longNumber = 1234567890123456789l;- 双精度浮点数:使用`double`关键字,通常以`d`或`D`结尾,但在不指定的情况下默认为双精度。// 等于十进制的123。- 十六进制:以`0x`或`0X`开头,后面跟着十六进制数字(0-9, A-F)。- 二进制:以`0b`或`0B`开头,后面跟着二进制数字(0, 1)。- 单精度浮点数:使用`float`关键字,通常以`f`或`F`结尾。- 长整数:使用`long`关键字,通常以`L`或`l`结尾。原创 2026-08-19 10:41:28 · 229 阅读 · 0 评论 -
C#:函数参数指定默认值
在上面的代码中,`CalculateDiscountedPrice` 方法接受两个参数:`price` 和 `discountRate`。`discountRate` 有一个默认值 `0.1m`,这意味着如果在调用这个方法时没有提供 `discountRate`,它将默认使用10%的折扣率。在C#中,可以为函数参数指定默认值,这样调用函数时可以不传递该参数,而是使用默认值。从C#6.0开始,可以直接在方法签名中为参数指定默认值,而不需要使用可选参数的特性(`[Optional]`)原创 2026-08-19 10:32:36 · 207 阅读 · 0 评论 -
C#:字符串做20位截断
虽然这不是最直接的方法,但如果想要一个更函数式的方法,可以使用LINQ的`Take`方法。在C#中,如果需要对字符串进行20位截断处理,即如果字符串长度超过20个字符,则只保留前20个字符,可以使用几种不同的方法来实现这一功能。string originalString = "这是一个很长的字符串,需要被截断。string originalString = "这是一个很长的字符串,需要被截断。string originalString = "这是一个很长的字符串,需要被截断。方法5:使用扩展方法。原创 2026-08-19 10:27:36 · 172 阅读 · 0 评论 -
C#:取的多个药品批准文号中的一个
在C#中,如果想匹配一个字符串,比如“国药准字HJ20090910 国药准字HJ20090911”,并找出其中所有以“国药准字”开头的部分,可以使用正则表达式(Regex)来实现这一功能。如果你想匹配中文和字母数字,可以使用`[\u4e00-\u9fa5a-zA-Z0-9]+`。string pattern = @"国药准字([\u4e00-\u9fa5a-zA-Z0-9]+)";- `match.Groups[1].Value` 用于获取第一个捕获组的内容,即“国药准字”后面的内容。原创 2026-08-18 16:10:08 · 149 阅读 · 0 评论 -
C#:List<string>特定格式输出
在C#中,如果有一个`List<string>`类型的列表,并且想要以特定格式(例如,用`|`分隔每个字符串)输出这些字符串,可以使用多种方法。LINQ的`Aggregate`方法也是一个很好的选择,它可以让你在单个表达式中完成连接和分隔符的添加。`String.Join`方法非常适合用来将集合中的元素连接成一个字符串,可以指定一个分隔符。如果不想使用`String.Join`,也可以通过遍历列表并手动构建字符串。方法3:使用LINQ的`Aggregate`方法。方法1:使用`String.Join`原创 2026-08-18 13:19:23 · 199 阅读 · 0 评论 -
C#:根据Model的字段名称自动匹配替换值到动态模板中
/ 注意:需要引用Microsoft.Extensions.DependencyInjection包。// 注意:需要引用Microsoft.Extensions.DependencyInjection包。// 注意:需要引用Microsoft.Extensions.DependencyInjection包。// 注意:需要引用Microsoft.Extensions.DependencyInjection包。原创 2026-08-18 11:05:47 · 174 阅读 · 0 评论 -
C#:`|`(管道符)连接字符串
在C#中,如果想将多个字段的值通过`|`(管道符)连接成一个字符串,可以使用几种不同的方法。最常见和直接的方法是使用`string.Join`方法或者字符串插值(String Interpolation)。方法4:使用LINQ的`String.Concat`和`Aggregate`方法(适用于复杂逻辑)// 使用LINQ的Aggregate方法连接字段,这里我们简单地连接所有非空字段,并用管道符分隔。// 使用string.Join连接字段。方法1:使用`string.Join`方法2:使用字符串插值。原创 2026-08-18 10:06:14 · 389 阅读 · 0 评论 -
C#:问号
Item`),任一环节为 `null` 即短路返回 `null`;`(可空类型修饰符):用于值类型(如 `int`, `bool`),使其能赋值为 `null`,等价于 `Nullable<T>`。.`(空条件成员访问):安全访问对象成员,若对象为 `null` 则整式返回 `null`,不抛异常。=`(空合并赋值运算符):仅当左操作数为 `null` 时,将右操作数赋值给左操作数(C8.0+)。[]`(空条件索引访问):安全访问数组/集合索引,若对象为 `null` 则返回 `null`。原创 2026-08-11 15:23:44 · 290 阅读 · 0 评论 -
C#:医保诊断数量限制
2. 字符串拼接:遍历前 `diagCount` 个元素,将序号(从 1 开始)与诊断名称拼接,格式为"1、名称;- 边界检查:确保 `strDiNameArr` 长度不小于 `diagCount`,避免索引越界异常。3. 潜在风险:在循环内使用 `+` 进行字符串拼接会导致频繁创建临时对象,若数据量较大可能影响性能。- 末尾分隔符处理:当前逻辑会在最后一个诊断后保留分号,若接口要求严格格式,需移除末尾多余符号。// 若需移除末尾分号:if (sb.Length > 0) sb.Length--;原创 2026-08-11 14:40:40 · 246 阅读 · 0 评论 -
C#:LINQ查询结果物化
LINQ查询结果物化是指将原本处于延迟执行状态的LINQ查询表达式,立即执行并将结果缓存到内存中的具体集合对象的操作,它是C# LINQ开发中控制查询执行时机、避免重复执行的关键操作。数据库查询注意事项:EF Core场景下,不要在物化后的内存集合上执行复杂筛选、排序操作,应尽可能将筛选逻辑放在物化前,让数据库执行高效的SQL查询,避免全表数据加载到内存后再处理。物化的作用:通过特定方法将查询结果一次性加载到内存中,生成独立的集合副本,彻底终止延迟执行,避免后续多次遍历引发的重复执行问题。原创 2026-08-10 14:50:16 · 686 阅读 · 0 评论 -
C#中.ToArray()方法
方法定位:它是LINQ提供的扩展方法,定义在System.Linq命名空间下,可将所有实现IEnumerable<T>接口的集合(如List<T>、LINQ查询结果)转换为同类型的数组T[]。性能开销:每次调用都会触发一次完整的O(n)遍历和内存分配,处理百万级以上的大型集合时,频繁调用会产生额外内存开销,需谨慎使用。数据隔离性:转换后的数组是完全独立的副本,对原集合的增删改操作不会影响数组内容,反之修改数组也不会同步到原集合。,会终止LINQ的延迟执行特性,直接缓存结果。原创 2026-08-10 14:47:26 · 456 阅读 · 0 评论 -
C#中IEqualityComparer接口
集合容器适配:作为HashSet<T>、Dictionary<TKey,TValue>的构造参数,自定义键的相等判断逻辑,实现复杂对象作为字典键的场景。必须保证Equals和GetHashCode的逻辑完全一致:若两个对象Equals返回true,哈希码必须相同,否则会出现哈希冲突、集合查找失败的问题。接口定义:它是.NET提供的泛型相等比较接口,用于自定义对象的相等判断逻辑,默认的引用类型比较是判断内存地址,该接口可实现按属性值自定义相等规则。大幅简化了自定义相等比较的代码量。原创 2026-08-10 14:43:35 · 336 阅读 · 0 评论 -
C#:typeof与getType
例如,你可以使用`GetProperties()`、`GetMethods()`等方法来获取关于类型的详细信息。在C#中,`typeof` 关键字用于获取一个类型的`Type`对象。另一种获取类型信息的方法是使用对象的`GetType()`方法。这个方法返回表示当前实例的运行时类型的`Type`对象。可以使用`typeof`操作符后面跟一个类型名来获取该类型的`Type`对象。这将返回`int`类型的`Type`对象,即是在一个变量上调用该方法。这将获取`int`类型的`Type`对象。原创 2026-08-07 11:11:32 · 315 阅读 · 0 评论 -
C#:Type
在 C#中,如果遇到了“Type 是一个类型,但在给定上下文中无效”这样的错误信息,这通常指的是在某个特定的表达式或语句中,尝试使用了 `Type` 类型,但使用方式不正确或者上下文不允许这样做。if (type == int) { // 这里会引发错误,因为 type 是 Type 类型,不能直接与基本类型比较。if (type == typeof(int)) { // 使用 typeof 获取正确的 Type 对象进行比较。// 这里会引发错误,因为不能直接将 Type 对象赋值给 int 类型。原创 2026-08-07 10:47:16 · 197 阅读 · 0 评论 -
C#:“不可访问,因为它受保护级别限制”
在C#中,当你遇到“不可访问,因为它受保护级别限制”的错误时,这通常意味着试图访问一个类、方法或属性,但是使用的访问修饰符(如 `private`、`protected`、`internal`、`protected internal` 或 `public`)阻止了这种访问。在这个例子中,`DerivedClass` 可以直接调用 `BaseClass` 中的 `ProtectedInternalMethod`,因为它是从派生类中访问的,并且该方法使用了 `protected internal` 修饰符。原创 2026-08-05 15:04:22 · 196 阅读 · 0 评论
分享