Skip to content

C# 开发疑难排障与小技巧 ​

本文汇总了在 C# 与 .NET 开发过程中遇到的典型问题及其解决方案,旨在通过经验沉淀减少重复排障时间。

1. 数据库访问:参数化查询与 Null 值处理 ​

问题描述 ​

在使用 SqlCommand 进行参数化查询时,如果直接传递 C# 的 null,可能会报错:“需要参数但未提供该参数”。

核心原理 ​

  • C# 的 null:表示对象引用无效。
  • 数据库的 NULL:在 .NET 中由 DBNull.Value 表示。
  • 如果将 SqlParameter.Value 设为 null,ADO.NET 会认为你没有为该参数赋值,从而尝试使用数据库中定义的默认值(如果没定义则报错)。

解决方案 ​

在赋值前进行转换:

csharp
public object ToDbValue(object value)
{
    return value ?? DBNull.Value;
}

// 使用示例
cmd.Parameters.AddWithValue("@nickname", ToDbValue(user.Nickname));

2. Base64 编解码深度排障 ​

2.1 长度无效问题 (Padding) ​

现象:报“Base-64 字符数组或字符串的长度无效”。 原因:Base64 字符串长度必须是 4 的倍数。如果数据在传输过程中丢失了末尾的 = 填充符,会导致解码失败。 修复:手动补齐填充符。

csharp
public string SafeDecodeBase64(string content)
{
    var encryptedContent = content.Trim().Replace(" ", "+");
    // 补齐末尾的 '='
    if (encryptedContent.Length % 4 > 0)
    {
        encryptedContent = encryptedContent.PadRight(encryptedContent.Length + 4 - encryptedContent.Length % 4, '=');
    }
    return Encoding.UTF8.GetString(Convert.FromBase64String(encryptedContent));
}

2.2 URL 安全的 Base64 ​

在 URL 中传递 Base64 时,+、/ 和 = 具有特殊含义。

  • 推荐做法:使用 Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode。
  • 手动替换:将 + 换成 -,/ 换成 _,并去掉末尾的 =。

2.3 算法实现差异 (Java 互操作) ​

不同类库(如 Apache Codec 与 BouncyCastle)的实现细节不同。例如 Apache 的 encodeBase64(data, true) 会按 RFC2045 每 76 字符加换行符。与外部系统对接时需确保标准一致。

3. LINQ 性能:Any() vs Count() ​

性能结论 ​

  • 内存集合 (List<T>, Array):使用 Count > 0 更快。因为 Count 是属性读取,而 Any() 需要创建 IEnumerator。
  • 延迟加载集合 (IEnumerable + yield return):必须使用 Any()。Count() 会触发全表遍历,而 Any() 只要找到第一个元素就返回。
  • 外部数据源 (LINQ to SQL/Entities):推荐使用 Any()。它会被翻译为 SQL 的 EXISTS,性能远高于 COUNT(*)。

4. 语法与资源管理 ​

4.1 属性默认值设置 ​

  • C# 6.0+:public int X { get; set; } = 100;
  • 旧版本:需使用私有字段(Backing Field)手动实现 get 和 set。
  • 注意:[DefaultValue] 特性仅用于元数据描述(如反射或属性窗口显示),不会自动初始化属性值。

4.2 使用嵌入的资源 ​

将配置文件或模板嵌入 DLL 中,运行时释放:

  1. 文件属性设置“生成操作”为“嵌入的资源”。
  2. 代码读取:
csharp
var assembly = GetType().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("命名空间.资源文件名"))
{
    if (stream != null)
    {
        byte[] bs = new byte[stream.Length];
        stream.Read(bs, 0, (int)stream.Length);
        File.WriteAllBytes(targetPath, bs);
    }
}

5. 参考资料 ​

  • [C# 性能测试:Any 与 Count 对比 - 博客园]
  • [Base64 编码原理与常见坑点 - 简书]
  • [.NET 参数化查询常见错误 - 博客园]

方舟 · Ark