• C# 编码规范


    前言

    从业多年,不断发现有很多团队的代码写的很随意,各种风格、命名方式都有,有用c++风格的,有用java风格的。所以本人在这里介绍下微软官方的C#编码规范规范本身内容其实不多,但是如果能认证看一遍的话,相信对你以后的开发会有很大帮助。

    注:本文不是一定适用所有人和所有团队,供大家参考。

    如有需要,请大家制定出自己的代码规范之前,参考以下两个准则:

    1. KISS(Keep It Simple and Stupid)
    2. 默认的就是最好的。

    正确的规范

    1. 命名规范 Pascal or camelCasing ?

    C#的命名有两种约定:Pascal和驼峰。

    • Pascal: 成员名的每个单词的首位字母大写,如:StudentStudentNameStudentParentName
    • 驼峰:成员名除了第一个单词外其余首字母都大写,StudentstudentNamestudentParentName.

    1.1 Pascal命名的使用场合

    1. classrecordrecord的参数、struct的名称,如:
    public class StudentInfo
    {
    }
    
    //record及record的参数
    public record StudentAddress(string NameInfo,int Age);
    
    public struct StudentDetail
    {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 接口名(第一个字母应为大写的I,可以清楚的表明是interface),如:
    public interface IStudentName
    {
    }
    
    • 1
    • 2
    • 3
    1. public的成员也应为Pascal命名,这些成员包括字段、属性、事件。方法名也应遵循Pascal命名,无论其是否是public。如:
    public class StudentInfo
    {
    	//公共字段
    	public bool IsValid;
    	//公共属性
    	public IWorkQueue WorkQueue{get;set;}
    	//公共事件
    	public event Action EventProcessing;
    	//公共方法
    	public void Run()
    	{
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.2 驼峰命名的使用场合

    1. 命名privateinternal字段时使用驼峰命名,且字段名应以_开头。如:
    public class DataService
    {
        private IWorkerQueue _workerQueue;
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 如果是staticprivateinternal的字段,则字段名应该以s_开头,对于线程静态则应该使用t_开头。如:
    public class DataService
    {
        private static IWorkerQueue s_workerQueue;
    
        [ThreadStatic]
        private static TimeSpan t_timeSpan;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 编写方法的参数名时,也应该以驼峰命名,如:
    public T SomeMethod<T>(int someNumber, bool isValid)
    {
    }
    
    • 1
    • 2
    • 3

    2. 布局规范

    1. 使用vs自带的代码编辑器设置,不要做过多个性化改动
    2. 每行只写一条语句:
    //正确
    int a=0;
    int b=0;
    //错误
    int a=0;int b=0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 未缩进的要缩进。
    2. 方法和属性之间至少要有一个空白行
    public int Age{get;set;}
    
    //正确,此注释行的上方留了一行空白,不能贴紧
    public void Run()
    {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. C#的大括号采用的是Allman style,大括号单独一行。以下是正确的:
    public void Run()
    {
    }
    
    • 1
    • 2
    • 3

    以下是错误的

    public void Run(){
    }
    
    • 1
    • 2

    3. 注释规范

    1. 注释应单独一行,不能放到代码末尾。
      以下是错误做法
    int i=0;//定义i并初始化
    
    • 1

    以下是正确的做法:

    // 定义i并初始化. Define i and init.
    int i=0;
    
    • 1
    • 2
    1. 如果注释为英文的话,则第一个单词的首字母应大写,即应符合英文的书写规范。
    2. 注释的双斜线(//)与具体注释文本之间应隔开一个空格,且注释应该以句号结尾。以下是错误的,因为//与“定”字之间没有空格且最后没有句号
    //定义i并初始化
    int i=0;
    
    • 1
    • 2
    1. 确保所有的public的成员都要有注释。

    4. 代码规范

    4.1 委托

    尽量使用自带的Func<>Action<>,避免自定义委托。

    4.2 using

    使用using来简化代码,简化资源的Dispose

    Font font1 = new Font("Arial", 10.0f);
    try
    {
        byte charset = font1.GdiCharSet;
    }
    finally
    {
        if (font1 != null)
        {
            ((IDisposable)font1).Dispose();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    以上代码可以简化为

    using (Font font2 = new Font("Arial", 10.0f))
    {
        byte charset2 = font2.GdiCharSet;
    }
    
    • 1
    • 2
    • 3
    • 4

    在C# 8中可以进一步简化为:

    using Font font3 = new Font("Arial", 10.0f);
    byte charset3 = font3.GdiCharSet;
    
    • 1
    • 2

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

    以下是正确的:

    var instance3 = new ExampleClass { Name = "Desktop", ID = 37414,
        Location = "Redmond", Age = 2.3 };
    
    • 1
    • 2

    以下是不建议的

    var instance4 = new ExampleClass();
    instance4.Name = "Desktop";
    instance4.ID = 37414;
    instance4.Location = "Redmond";
    instance4.Age = 2.3;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.4 事件处理

    如果你在定义一个稍后不需要手动删除的事件处理程序,则应该使用lambda表达式

    public Form2()
    {
        this.Click += (s, e) =>
            {
                MessageBox.Show(((MouseEventArgs)e).Location.ToString());
            };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    错误的做法

    1. 变量名里不要包含变量类型,因为“词不一定达意”且会产生误导

    以下是错误的,从名字上看inputInt应该是int类型,但其实是string类型。

    var inputInt = Console.ReadLine();
    Console.WriteLine(inputInt);
    
    • 1
    • 2

    2. 可以在for中使用var,但不要在foreach中使用var

    以下都是正确的:

    for (var i = 0; i < 10000; i++)
    {
        manyPhrases.Append(phrase);
    }
    
    • 1
    • 2
    • 3
    • 4
    foreach (char ch in laugh)
    {
        if (ch == 'h')
            Console.Write("H");
        else
            Console.Write(ch);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因为laugh集合中的元素类型是什么并不明显,使用var的话可读性不强,不如直接明确char

    标准范文

    以下是符合C# 编码规范的标准范文,你可以进行参考:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Diagnostics;
    using Microsoft.Win32;
    
    namespace System.Collections.Generic
    {
        public partial class ObservableLinkedList<T> : INotifyCollectionChanged, INotifyPropertyChanged
        {
            private ObservableLinkedListNode<T> _head;
            private int _count;
    
            public ObservableLinkedList(IEnumerable<T> items)
            {
                if (items == null)
                    throw new ArgumentNullException(nameof(items));
    
                foreach (T item in items)
                {
                    AddLast(item);
                }
            }
    
            public event NotifyCollectionChangedEventHandler CollectionChanged;
    
            public int Count
            {
                get { return _count; }
            }
    
            public ObservableLinkedListNode AddLast(T value)
            {
                var newNode = new LinkedListNode<T>(this, value);
    
                InsertNodeBefore(_head, node);
            }
    
            protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                NotifyCollectionChangedEventHandler handler = CollectionChanged;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
    
            private void InsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
            {
                ...
            }
    
            ...
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    提示

    1. vs代码格式化快捷键:Ctrl+K+D
    2. C#代码格式化整理插件:CodeMaid (vs插件市场直接搜索安装)

    引用:

    1. C# 编码约定
    2. C# coding style
    3. dotnet-format 格式化工具
  • 相关阅读:
    实验三十四、串联型稳压电路参数的选择
    实用电脑软件安利,朋友们快来挖宝
    小波函数绘制(Python)
    Go 语言 设计模式-工厂模式
    小程序 + dayjs自定义 picker 时间选择器
    SRM系统可以为企业带来什么价值?
    nginx配置反向代理和动静分离应用
    知识问答产品利器:文本分段器实现自动知识加工
    关于uniapp嵌入iframe的问题
    django自动生成问卷表的软件的设计与实现毕业设计源码291138
  • 原文地址:https://blog.csdn.net/catshitone/article/details/126411812