欢迎来到新一期的5个C#和.NET开发技巧!抱歉过去两个月断更——上次更新还是在二月份——这段时间确实忙得不可开交,而且撰写这些技术文章总比预期耗时更长。
本期内容包含:避免直接使用DateTime.Now、Entity Framework Core的全局查询过滤器、并发集合、用户密钥管理、Base64Url编码技巧。
每个开发者都有独特的编程风格,这很好。但我们都会掌握一些他人可能不知道的技巧。本文我将分享个人最常用的5个C#/.NET开发秘籍。有些你可能熟悉,有些或许陌生,也可能某些并不适用于你的场景。
这些技巧的呈现方式不会长篇大论,而是通过简明描述和示例代码展示核心思想。如果对任何技巧有疑问,欢迎在评论区留言。若某主题需求旺盛,我会专门为它撰写完整文章。
本文大部分示例基于以下类定义、枚举和列表:
public class Product
{
public int Id { get; set; }
public string? Title { get; set; }
public int Stock { get; set; }
public Status Status { get; set; }
public bool Available { get; set; }
}
public enum Status
{
Ordered,
Delivered,
Delayed,
Unknown
}
List<Product> products =
[
new() { Id = 1, Title = "7Up", Status = Status.Ordered, Stock = 10, Available = true },
new() { Id = 2, Title = "Chips", Status = Status.Ordered, Stock = 0, Available = true },
// 其他产品数据...
];
(适用版本:.NET 1+)
这个标题可能有些绝对,但为了简洁我保留了它。大多数开发者会直接用DateTime.Now获取当前时间——这本就是它的设计目的,不是吗?但它存在一些可能引发重大问题的缺陷:
解决方案是使用DateTimeOffset.UtcNow
:
var timestamp = DateTime.Now; // 能用但不推荐
// 替代方案
var timestamp = DateTimeOffset.UtcNow; // 更优选择
为了支持单元测试,可以创建返回DateTimeOffset的接口,在需要时注入依赖:
public interface IDateTimeProvider
{
DateTimeOffset GetCurrentTime();
}
// 生产环境实现
public class DateTimeProvider : IDateTimeProvider
{
public DateTimeOffset GetCurrentTime() => DateTimeOffset.UtcNow;
}
// 测试环境可模拟实现
(适用版本:Entity Framework Core)
当需要频繁对某实体应用相同查询条件时(比如99%的场景只需要查询可用商品),EF Core的全局查询过滤器能消除重复代码。以下是不使用过滤器的常规做法:
using (var context = new ProductsContext())
{
var availableProducts = context.Products
.Where(x => x.Available)
.ToList();
}
在DbContext的OnModelCreating方法中配置全局过滤器:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasQueryFilter(x => x.Available);
}
之后所有查询都会自动应用该条件。如需临时禁用,使用IgnoreQueryFilters()
:
var allProducts = context.Products
.IgnoreQueryFilters()
.ToList();
(适用版本:.NET Framework 4+)
标准集合类型(如List
var concurrentDict = new ConcurrentDictionary<int, Product>();
Parallel.ForEach(products, product =>
{
concurrentDict.TryAdd(product.Id, product);
});
if (concurrentDict.TryGetValue(1, out var foundProduct))
Console.WriteLine($"找到产品:{foundProduct.Title}");
注意:
(适用版本:Visual Studio 2015, .NET Core 1+)
敏感信息不应存储在appsettings.json中。Visual Studio的"管理用户密钥"功能可将开发环境密钥存储在用户个人目录:
%APPDATA%\microsoft\UserSecrets\<GUID>\
){
"Products": {
"ConnectionString": "你的连接字符串"
}
}
通过配置系统读取:
var config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
Console.WriteLine(config["Products:ConnectionString"]);
生产环境推荐使用Azure Key Vault或AWS Secrets Manager。
(适用版本:.NET 9)
传统Base64编码会产生URL不友好字符(+/=)。.NET 9新增的Base64Url工具类:
var bytes = Encoding.UTF8.GetBytes("Coffee with milk");
var standardBase64 = Convert.ToBase64String(bytes); // 含特殊字符
var urlSafe = Base64Url.EncodeToString(bytes); // URL友好格式
以上就是本期的5个C#/.NET开发技巧。无论这些技巧对你来说是新知还是旧识,希望都能有所启发。如果你有独家技巧想要分享,欢迎在评论区留言——它们可能会出现在下期内容中!