【.NET Core】常见C#代码约定

简介: 【.NET Core】常见C#代码约定

一、概述

代码标准对于在开发团队中维护代码可读性、一致性和协作至关重要。 遵循行业实践和既定准则的代码更易于理解、维护和扩展。 大多数项目通过代码约定强制要求样式一致。本文我们将讨论编码约定和用于强制实施这些约定的工具。

二、代码预定的目标

  • 正确性

在编辑代码时,需要代码具有复原能力且正确无误,即使在多次编辑之后也是如此。

  • 一致性

在编写代码中,我们需要遵循相同的规则,使之在整个项目周期中遵循相同的规则样式。


三、代码约束工具和分析器

工具可帮助团队强制实施标准。可以启用代码分析来强制实施代码规则。可以创建editorconfig,以便Visual Studio可自动强制实施样式标准。


借助这些工具,团队可以更轻松地采用首选的标准。Visual Studio将在范围中的所有.editorconfig文件中应用规则,以设置代码的格式。可以使用多个配置来强制实施企业范围的标准、团队标准甚至精细的项目标准。


启用的规则被违反时,代码分析会生成警告和诊断。可以配置想要应用于项目的规则。然后,每个CI生成会在违反任何规则时通知开发人员。


四、C#语言准则

一般情况C#需要遵从以下准则:

  • 尽可能利用新式语言功能和 C# 版本
  • 避免陈旧或过时的语言构造
  • 仅捕获可以正确处理的异常;避免捕获泛型异常
  • 使用特定的异常类型提供有意义的错误消息
  • 使用 LINQ 查询和方法进行集合操作,以提高代码可读性
  • 将异步编程与异步和等待用于 I/O 绑定操作
  • 谨慎处理死锁状态,并在适当时使用Task.ConfigureAwait
  • 对数据类型而不是运行时类型使用语言关键字。例如:定义字符串使用string而不是System.String,或使用int而不是System.Int32
  • 使用 int 而不是无符号类型。 int 的使用在整个 C# 中很常见,并且当你使用 int 时,更易于与其他库交互。 特定于无符号数据类型的文档例外
  • 仅当读者可以从表达式推断类型时使用 var
  • 以简洁明晰的方式编写代码
  • 避免过于复杂和费解的代码逻辑


五、字符串约定

5.1 使用字符串内插来连接短字符串

string displayName = $"{JsonList[n].LastName}, {JsonList[n].FirstName}";

5.2 插入大文本时,使用System.Text.StringBuilder对象

var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
    manyPhrases.Append(phrase);
}
var response = stringBuilder.ToString();

六、数组约定

  • 当在声明行上初始化数组时,请使用简洁的语法
string[] vowels1 = { "H", "O", "O", "L", "G" };
  • 如果使用显式实例化,则可以使用 var
var word=new String[]{"G","O","Y","E","E","R"};

七、委托约定

7.1 使用Func<>Action<>,而不是定义委托类型

Action<string> actionExample1 = x => Console.WriteLine($"x is: {x}");
Action<string, string> actionExample2 = (x, y) =>
    Console.WriteLine($"x is: {x}, y is {y}");
Func<string, int> funcExample1 = x => Convert.ToInt32(x);
Func<int, int, int> funcExample2 = (x, y) => x + y;

7.2 使用Func<>Action<>委托定义的签名来调用方法

actionExample1("string for x");
actionExample2("string for x", "string for y");
Console.WriteLine($"The value is {funcExample1("1")}");
Console.WriteLine($"The sum is {funcExample2(1, 2)}");

7.3 如果创建委托类型的实例,请使用简洁的语法

public delegate void Del(string message);
public static void DelMethod(string str)
{
    Console.WriteLine("DelMethod argument: {0}", str);
}

7.4 创建委托类型的实例,然后调用该实例

Del exampleDel2 = DelMethod;
exampleDel2("Hey");

八、&&|| 运算符

8.1 在执行比较时,使用&& 而不是 &,使用||而不是|

Console.Write("Enter a dividend: ");
int dividend = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter a divisor: ");
int divisor = Convert.ToInt32(Console.ReadLine());
if ((divisor != 0) && (dividend / divisor) is var result)
{
    Console.WriteLine("Quotient: {0}", result);
}
else
{
    Console.WriteLine("Attempted division by 0 ends up here.");
}

九、new运算符

9.1 使用对象实例化的简洁形式

var firstExample = new ExampleClass();
ExampleClass instance2 = new();

前面的声明等效于下面的声明:

ExampleClass secondExample = new ExampleClass();

9.2 使用对象初始值设定项简化对象创建

var thirdExample = new ExampleClass { Name = "Desktop", ID = 37414,
    Location = "Redmond", Age = 2.3 };

十、静态成员

使用类名调用static成员:ClassName.StaticMember。通过明确静态访问使代码更易于阅读。请勿使用派生类的名称来限定基类中定义的静态成员。编译代码时,代码可读性具有误导性,如果向派生类添加具有相同名称的静态成员,代码可能会被破坏。

十一、LINQ查询

11.1 对查询变量使用有意义的名称

var seattleCustomers = from customer in customers
                       where customer.City == "Seattle"
                       select customer.Name;

11.2 使用别名确保匿名类型的属性名称都使用 Pascal 大小写格式正确大写

var localDistributors =
    from customer in customers
    join distributor in distributors on customer.City equals distributor.City
    select new { Customer = customer, Distributor = distributor };

11.3 如果结果中的属性名称模棱两可,请对属性重命名

var localDistributors2 =
    from customer in customers
    join distributor in distributors on customer.City equals distributor.City
    select new { CustomerName = customer.Name, DistributorID = distributor.ID };

11.4 在查询变量和范围变量的声明中使用隐式类型化

var seattleCustomers = from customer in customers
                       where customer.City == "Seattle"
                       select customer.Name;

11.5 对齐from子句下的查询子句,其他查询子句前面使用where子句,确保后面的查询子句作用于作用于经过缩减和筛选的一组数据

var seattleCustomers2 = from customer in customers
                        where customer.City == "Seattle"
                        orderby customer.Name
                        select customer;

11.6 使用多行 from 子句代替join子句来访问内部集合

var scoreQuery = from student in students
                 from score in student.Scores!
                 where score > 90
                 select new { Last = student.LastName, score };

十二、隐式类型本地变量

12.1 当变量的类型在赋值右侧比较明显时,对局部变量使用隐式类型

var message = "This is clearly a string.";
var currentTemperature = 27;

12.2 当类型在赋值右侧不明显时,请勿使用var

int numberOfIterations = Convert.ToInt32(Console.ReadLine());
int currentMaximum = ExampleClass.ResultSoFar();

12.3 不要使用变量名称指定变量的类型

12.4 避免使用var来替代dynamic

如果想要进行运行时类型推理,请使用 dynamic

12.5 在for循环中对循环变量使用隐式类型

var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
    manyPhrases.Append(phrase);
}

12.6 不要使用隐式类型在foreach循环中类型

不要使用隐式类型化来确定 foreach循环中循环变量的类型。 在大多数情况下,集合中的元素类型并不明显。 不应仅依靠集合的名称来推断其元素的类型。

12.7 对 LINQ 查询中的结果序列使用隐式类型

关于LINQ的部分说明了许多LINQ查询会导致必须使用隐式类型的匿名类型。其他查询则会产生嵌套泛型类型,其中var的可读性更高。


十三、注释样式

  • 使用单行注释(//)以进行简要说明
  • 避免使用多行注释(/* */)来进行较长的解释。 注释不进行本地化处理。 相反,配套文章中提供了较长的解释
  • 若要描述方法、类、字段和所有公共成员,请使用XML注释
  • 将注释放在单独的行上,而非代码行的末尾
  • 以大写字母开始注释文本
  • 以句点结束注释文本
  • 在注释分隔符 (//) 与注释文本之间插入一个空格
目录
相关文章
|
11天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
34 5
|
8天前
|
开发框架 监控 .NET
C#进阶-ASP.NET WebForms调用ASMX的WebService接口
通过本文的介绍,希望您能深入理解并掌握ASP.NET WebForms中调用ASMX WebService接口的方法和技巧,并在实际项目中灵活运用这些技术,提高开发效率和应用性能。
25 5
|
29天前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
39 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
16天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
62 13
|
19天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
24 3
|
20天前
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
1月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
24 3
|
1月前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
24天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
|
24天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(下)
本文接续前文,深入讲解了在Windows环境下使用C#和ADO.NET操作南大通用GBase 8s数据库的方法。通过Visual Studio 2022创建项目,添加GBase 8s的DLL引用,并提供了详细的C#代码示例,涵盖数据库连接、表的创建与修改、数据的增删查改等操作,旨在帮助开发者提高数据库管理效率。