编写更好的 C# 代码的更多技巧
介绍
在阅读本指南之前,请先查看本系列的第一本指南《编写更好的 C# 代码简介》和《编写更好的 C# 代码的技巧》。
阅读本指南之前您应该了解以下几件事:
- C# 第 6 版中的改进
- .NET 框架中的 LINQ
- C# 中的异步编程和Task对象
- C# 中的不安全编程,允许你进入内存管理
不注重绩效
需要注意的是,我不会谈论改变程序性能、提高效率或减少程序运行所需的时间。通过编写良好的 C# 代码,您可以在几秒钟内提高程序性能,但以下提示并不能保证您的代码性能会更好。
循环遍历大量数据
如果不能对数据集合进行循环和迭代,那么应用程序还有什么用呢?在这些情况下,有时您必须查找值、查找节点、查找记录或对集合执行任何其他遍历。在这种情况下,您确实需要确保编写的代码干净,因为这是性能和可读性都非常重要并且相互关联的领域。凭借一些经验,我能够克服编写读取和遍历数据的代码的错误方式。这正是 LINQ 经验应该发挥作用的地方,它允许您编写使用最佳 .NET 框架的程序,从而为您的用户和客户提供最佳的编码体验和最佳体验。
以前,您可能已经做过以下一些事情:
// A function to search for people
Person FindPerson(int id) {
var people = DbContext.GetPeople(); // Returns List<Person>
foreach (var person in people) {
if(person.ID == id) {
return person;
}
}
// No person found.
return null;
}
// Then do this
var person = FindPerson(123);
对于任何想进入您所在领域的人士来说,这都是一篇易读的文章。但是,使用 C# 中的 LINQ 查询可以使代码更简单、更清晰。有两种方法可以做到这一点。一种是有点类似 SQL,另一种是通过对集合使用Where函数并传递我们的要求。
// A function to search for people
Person FindPerson(int id) {
var people = DbContext.GetPeople(); // Returns List<Person>
return (from person in people
where person.ID == id
select person).ToList().FirstOrDefault();
}
// Then do this
var person = FindPerson(123);
此代码看起来有点像 SQL,可以增强代码的可读性和性能。该函数类似,但是,Where函数的可读性更好一些,并将所有迭代都留给.NET 框架本身。.NET 框架将为应用程序提供最佳性能。现在,让我们看看在相同的 C# 代码中编写此查询的另一种方法:
// A function to search for people
Person FindPerson(int id) {
var people = DbContext.GetPeople(); // Returns List<Person>
return people.FirstOrDefault(x => x.ID == id);
}
// Then do this
var person = FindPerson(123);
请注意,第一个代码在没有找到匹配项的情况下返回null 。此代码也执行相同的操作。第一个代码唯一更糟糕的是它必须对集合本身执行迭代。该 local return person;将允许程序返回控制权,但如果数据位于最后一个位置会发生什么?此数据搜索算法的复杂度仍为 O(n)。
避免不安全的上下文
在您必须亲自驾驶飞机时,C# 还支持手动内存管理。C# 中的不安全上下文允许您操作内存、执行指针运算、在可能无法访问的内存位置读取和写入数据等等。但是,.NET 框架做了很多事情来克服内存问题、延迟和磁盘上的其他问题。这也使 .NET 框架能够克服实际执行任何内存管理的需要,.NET 框架会为您完成这项工作。
使用不安全上下文有很多好处,例如当您想要编写本机 C++ 库的包装器时。Emgu CV 就是这样一个例子,您可以编写一些代码来处理本机代码的管理方式,并以更简单的方式处理内存中的错误。在这种情况下,您可以:
- 使用指针管理和指针算法。您不能在此上下文之外的地址上执行任何操作,这是 .NET 规则所在。
- 使用内存管理来操作内存中的对象。
- 使用 C++ 风格的编程,这正是 C# 的设计目的。
这样做几乎没有任何好处,如果您需要在应用程序中考虑这一点,请明智地考虑。
关于 Unsafe 的一切都只是个人观点
我还想指出,我所说的关于“不安全”的利弊都是我的个人观点。我在我的程序中不经常使用不安全上下文,因为我没有理由在我的应用程序中考虑使用它。但是,如果您的应用程序需要本机内存管理,那么您可以使用此上下文。
尽可能使用 Lambda 表达式
Lambda 源自函数式编程领域,在 C# 中它被广泛用于许多方面,从内联函数一直到 C# 6 中的仅 getter 属性。我将展示 C# 中的两种用法,它们不仅使程序看起来更酷,而且性能也更好;为此,我将向您展示该 C# 代码的 IL。我个人喜欢在许多领域使用 lambda,尤其是当我必须在 C# 中编写内联函数时。自从可以使用这个概念编写仅 getter 属性以来,我一直在使用它们,我个人认为它比以前做同样事情的方式更好。
1. 使用 Lambda 表达式实现内联函数
您应该了解一些 C# 编程中众所周知的委托。它们在许多领域都有用处,例如在应用程序中的事件处理中。对于事件处理,您可以编写当前的函数,如下所示:
// Without lamdbas
myBtn.Click += Btn_Click;
public void Btn_Click (object sender, EventArgs e) {
// Code to handle the event
}
// With the help of lambdas
myBtn.Click += (sender, e) =>
{
// Code to handle the event.
}
请注意,编译器会自动将对象映射到其类型。这在很多方面都很方便,因为它允许您在 C# 中编写仅与对象一起保留的内联函数,除非您也想在其他任何地方使用它们。但是,这种处理事件的方法有一个缺点:一旦附加了事件处理程序,您就无法将其删除。在 C# 中,您可以-+但由于我们没有任何引用来删除事件,因此我们只能使用单独的函数。但是,如果您不必删除处理程序,则应始终考虑在程序中使用这种事件处理方式。
2. 使用 Lambda 表达式来获取仅包含 Getter 的属性
在 C# 中,有一个使用属性而不是字段的概念。您可以控制如何设置值以及如何从字段中捕获值。将其视为 Java 编程语言的 getter 和 setter 的替代(或类似)。唯一的区别是您不必将它们单独写在某处,它们写在字段本身的前面。然后,C# 程序编译器将创建自己的支持字段来存储值。
基本上,你必须像这样编写 getter-only 属性:
public string Name { get; }
请注意,这些属性是常量,一旦设置,就无法更改。它们是在构造函数中设置的,或者(从 C# 6 开始)在构造函数前面设置的。像这样:
public string Name { get; } = "Afzaal Ahmad Zeeshan";
但是,既然我们已经知道这是一个常量字段,并且无法修改它,那么为什么不创建一个简单的常量属性呢?事情变得有点棘手;即使是属性也必须由字段支持。在这种情况下,这将为我们解决问题:
public string Name => "Afzaal Ahmad Zeeshan";
这相当于编写以下内容:
public string Name { get { return "Afzaal Ahmad Zeeshan"; } }
但是性能要好得多,因为仅获取器的字段被转换为常量字段,并且该字段在程序中随时调用此属性。
最后的话
本指南系列的目的是让您了解和看到一些让您的程序更易于阅读和性能更好的方法。C# 编译器本身可以最大程度地提高代码的质量和效率,而这通常留给程序员,并将使程序运行得更好。还有许多其他方法可以提高可读性,其中许多都留给公司的编写程序的方式,因为大多数团队都要求程序员遵循自己的编程方法和方式。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~