这 5 条 C# 准则(由高级开发人员揭晓)将改变你的编码风格
学习编程可能充满挑战,但遵循经验丰富的开发人员的建议可以帮助您快速轻松地掌握编程基础知识。一位资深开发人员分享的这五条 C# 准则将改变您编写代码的方式;本文将向您展示如何立即像专业人士一样开始编程!
这些指导方针由HTEC Group的高级软件工程师Milan Jovanović提供,HTEC Group 是一家大型科技公司,仅在最新一轮投资中就筹集了高达1.4 亿美元的资金!
在 LINQ“查询”语法中定义临时变量
对于第一条指导原则,米兰评论说,有可能在 LINQ“查询”语法中定义临时变量。
这很令人好奇,因为他一直在与开发人员沟通,其中许多人完全不知道这个功能。因此,他决定解释一下:
使用 let 关键字,您可以在 LINQ 查询中定义一个临时值。您可以使用它进行进一步的计算,或者将该值作为结果返回。
from user in _dbContext.Set<User>().AsNoTracking()
where user.Id == userId
let name = $"{user.FirstName} {user.LastName}"
let hasFirstName = !string.IsNullOrEmpty(user.FirstName)
let hasLastName = !string.IsNullOrEmpty(user.LastName)
select new
{
user.Id,
Name = name,
ProfileComplete = hasFirstName && hasLastName
}
他提出的另一点是,在编写EF Core(实体)查询时,所使用的子句(let
)也会被转换为正确的 SQL。
此外,建议对其进行测试并检查生成的 SQL:
“并非所有内容都像内存 LINQ 那样受支持。”
📚在这里你可以阅读他的解释:在 LINQ“查询”语法中定义临时变量
Switch 语句来计算值
他还分享了使用 C# 编写简洁代码的最佳实践。我个人见过不少类似的案例,所以推荐大家去看看。
Milan 告诉我们,从 C# 8 开始,您可以使用 switch 表达式来替换 switch 指令。
不好的方法:
switch (DateTime.Now.DayOfWeek)
{
case DayOfWeek.Monday:
case DayOfWeek.Tuesday:
case DayOfWeek.Wednesday:
case DayOfWeek.Thursday:
case DayOfWeek.Friday:
return "Not Weekend";
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
return "Weekend";
default:
throw new ArgumentOutOfRangeException();
}
好方法:
DateTime.Now.DayOfWeek switch
{
not (DayOfWeek.Saturday or DayOfWeek.Sunday) => "Not Weekend",
DayOfWeek.Saturday or DayOfWeek.Sunday => "Weekend",
_ => throw new ArgumentOutOfRangeException()
}
此外,他还表示还有改进的空间:
“此外,从 C# 9 开始,我们可以添加逻辑模式匹配运算符,以获得更大的灵活性。”
📚在这里你可以阅读他的解释:Switch 语句来计算值
创建一个惰性线程安全单例实现
这里出现的问题是如何创建惰性线程安全单例实现。
根据米兰的说法,有多种方法可以做到这一点,但你应该始终依靠锁定来防止同时访问,以确保实现线程安全。
米兰警告说,这种做法需要对锁定机制有相当深入的了解。
“但是,我们可以利用 Lazy 类来‘懒惰地’实例化一个类的实例。”
public sealed class Singleton
{
private static readonly Lazy<Singleton> LazyInstance =
new Lazy<Singleton>(() => new Singleton());
private Singleton()
{
}
public static Singleton Instance => LazyInstance.Value;
}
最后,他评论说并发并不重要:
“Lazy 默认也是线程安全的,所以你不必‘考虑’并发性。”
📚在这里你可以阅读他的解释:创建一个惰性线程安全单例实现
创建和使用本地函数
对于那些不知道局部函数是什么的人来说,局部函数允许你在先前定义的方法体内声明一个方法。此功能是在 C# 7 中添加的,Milan 决定以一种清晰的方式解释它:
局部函数仅在其包含成员的范围内可见。通常,您会在另一个函数内部定义和使用它们。
public IEnumerable<string> CapitalizeFirstLetter(IEnumerable<string> enumerable)
{
if (!enumerable.Any())
{
throw new ArgumentException("The sequence is empty.");
}
return enumerable.Select(CapitalizeFirstLetterLocal);
static string CapitalizeFirstLetterLocal(string input) =>
input switch
{
null or "" => throw new ArgumentNullException(nameof(input)),
_ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1))
};
}
米兰补充的另一件事是,只要本地函数无权访问实例成员,它们也有可能成为静态的。
将局部函数与迭代器结合起来很有趣。
迭代器的设计是惰性的。但你可能希望快速执行参数检查,这时局部函数就派上用场了。
📚在这里你可以阅读他的解释:创建和使用本地函数
将局部函数与迭代器块组合
让我们继续讨论局部函数!这次 Milan 想分享的是,在进行即时参数检查的同时,使用迭代器块实现惰性求值的可能性。
请注意,本地函数使用了“yield return”语句,该语句在枚举发生时执行。如果迭代器块直接位于“ReadFileLineByLine”内部,则只有在枚举结果时才会引发异常。
public IEnumerable<string> ReadFileLineByLine(string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException(nameof(fileName));
}
return ReadFileLineByLineImpl();
IEnumerable<string> ReadFileLineByLineImpl()
{
foreach (var line in File.ReadAllLines(fileName))
{
yield return line;
}
}
}
这种良好做法使得在异常发生之前检测到它们成为可能:
“一旦调用“ReadFileLineByLine”,就会引发异常。”
📚在这里你可以阅读他的解释:将局部函数与迭代器块结合起来
再次感谢Milan Jovanović分享这些指南,为 C# 开发者社区带来宝贵的价值。如果您喜欢这些指南,我建议您在 Linkedin 上关注他,因为他一直很活跃,并且上传了大量有价值的 C# 内容!
鏂囩珷鏉簮锛�https://dev.to/bytehide/these-5-c-guidelines-revealed-by-a-senior-developer-will-change-your-coding-style-3jfp