告别 .NET Framework习惯,7个现代 C# 实践让你的代码更高效更安全
侧边栏壁纸
  • 累计撰写 1,021 篇文章
  • 累计收到 3 条评论

告别 .NET Framework习惯,7个现代 C# 实践让你的代码更高效更安全

私人云
2026-01-29 / 0 评论 / 0 阅读 / 正在检测是否收录...

.NET Core 和 .NET 8+ 带来了全新的应用构建方式——但许多开发者(和团队)仍被困在 .NET Framework 的习惯中。

资历不等于现代化某些代码能运行,并不代表它应该出现在你 2025 年的代码库里。

如果你一直在盲目复制资深同事的代码,可能会在不知不觉中导致应用性能更低、更难维护、更不安全。

让我们来解决这个问题。

1. 还在用ConfigurationManager?这是遗留 .NET 的做法

你可能在这样写

var conn = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;

问题所在

• 默认不适用于现代 .NET• 不支持环境配置或依赖注入(DI)• 无法绑定到强类型类

应该这样做

public class ApiSettings{public string ApiKey { get; set; }}// Startup 或 Program.csservices.Configure<ApiSettings>(config.GetSection("ApiSettings"));// 使用方式public class MyService(IOptions<ApiSettings> settings){var apiKey = settings.Value.ApiKey;}

现代配置 = 类型安全 + 环境感知 + 可注入。

2. 用DateTime.Now生成时间戳?这是在自找 Bug

旧习惯

var createdAt = DateTime.Now;

为什么不好

• 本地服务器时间 ≠ 全球统一时间• 在分布式系统中会出错• 夏令时令人头疼

现代 C# 的做法

var utc = DateTime.UtcNow;var offset = DateTimeOffset.UtcNow;

仅在显示时转换为本地时间,切勿用于存储。

必要时使用 TimeZoneInfo——但所有时间都应以 UTC 存储。

3. 对异步方法调用.Result?你正在阻塞线程

错误代码示例

var user = httpClient.GetStringAsync(url).Result;

实际后果

• 线程被阻塞• 可能发生死锁• 严重影响 ASP.NET Core 应用的可扩展性

彻底异步化

public async Task<IActionResult> GetUser(){var result = await _api.GetUserAsync();return Ok(result);}

如果你的方法调用了异步代码,请将其也改为异步。

不要和编译器对抗,让它赢。

4. 把所有服务都当作单例使用

新手操作

services.AddSingleton<DbContext>(); // ❌

风险

• DbContext 不是线程安全的• 会导致内存泄漏• 共享状态 = 共享 Bug

使用正确的生命周期

services.AddScoped<MyDbContext>();services.AddTransient<IEmailSender, EmailSender>();services.AddHttpClient<IMyApiClient, MyApiClient>();

使用 HttpClientFactory,别再到处 new HttpClient() 了。

5. 用字符串拼接构建 SQL 或 URL

仍在这样写

var query = $"SELECT * FROM Users WHERE Name = {name}";

或:

var url = "https://api.com/users?name=" + name + "&city=" + city;

☠️ 潜在问题

• SQL 注入• 编码错误• 维护噩梦

更安全、更智能的替代方案

// 使用 LINQ 或 EF Corevar users = await db.Users.Where(u => u.Name == name).ToListAsync();// 使用 UriBuilder 构建 URLvar builder = new UriBuilder("https://api.com/users");var query = HttpUtility.ParseQueryString("");query["name"] = name;query["city"] = city;builder.Query = query.ToString();var url = builder.ToString();

另外:在循环中始终使用 StringBuilder。

6. 忽略可空引用类型

你的代码可能长这样

public string Email { get; set; } // 可能为 null ♂️

隐患

• Null 是无声的杀手• 直到运行时才会发现问题• 现代 C# 可以避免空引用异常(NRE)

让编译器帮忙

<!-- 在 .csproj 中启用 --><Nullable>enable</Nullable>public string Email { get; set; } = string.Empty;public string? MiddleName { get; set; }

现在,当 Null 悄悄潜入时,编译器会发出警告。让它发挥作用。

7. 用异常控制流程

你会后悔的写法

try{return int.Parse(input);}catch{return 0; // 糟糕}

或者更糟:

if (user == null)throw new UserNotFoundException();

代价高昂

• 异常处理速度慢• 适用于异常情况,而非预期逻辑• 让流程难以阅读

使用更智能的模式

// TryParse 模式if (int.TryParse(input, out var value))return value;// 可选返回或 Result 模式public Result<User> GetUser(int id){var user = _db.Users.Find(id);return user != null? Result.Success(user): Result.Failure("User not found");}

你不需要用 throw 来表示“未找到”。

✨ 超越“能运行的代码”

❌ 旧习惯✅ 应该这样做ConfigurationManager使用 DI 的 IOptions<T>DateTime.Now使用 DateTimeOffset.UtcNow.Result / .Wait()正确使用 async/await单例 DbContext使用 Scoped 或 Transient 生命周期字符串拼接 SQL使用 LINQ / 参数化查询可空类型混乱启用可空引用类型用异常控制逻辑使用 TryParse 或 Result<T> 模式

最后一点建议

陈旧的习惯不属于现代应用。

如果你在团队的代码库中仍然看到这些做法,不要盲从——要带头改变。

资深开发者的价值不在于写了 10 万行代码,而在于知道什么不该写。

所以,停止这 7 种做法——即使你的技术负责人坚持相反的意见。

0

评论 (0)

取消