C#编码标准指导和最佳实践 之 编码实践

本文提供了一系列编码规范和最佳实践,包括代码长度、方法参数数量、异常处理、类型转换、接口使用等多个方面,帮助开发者写出高质量、易维护的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编码实践:


    1、避免在一个文件内写多于500行的代码(机器自动生成的代码除外)。

    2、避免写超过25行代码的方法。

    3、避免写超过5个参数的方法,如果要传递多个参数,使用结构。

    4、一行代码不要超过80个字符。

    5、尽可能使用 partial classes 特性,以提高可维护性。

    6、避免对很直观的内容作注释。注释应该只说明操作的一些前提假设、算法的内部信息等内容。

    7、避免对方法进行注释:
       a、使用充足的外部文档对API进行说明;
       b、只有对那些其他开发者的提示信息才有必要放到方法级别的注释中来。
 
    8、除了0和1,绝对不要对数值进行硬编码,通过声明一个常量来代替该数值。

    9、只对那些亘古不变的数值是要const关键字,例如一周的天数。

    10、避免对只读变量使用const关键字。在这种情况下,直接使用readonly关键字:
        public class MyClass
        {
            public const int DayinWeek = 7;
            public readonly int Number;
            public MyClass(int someValue)
            {
                Number = someValue;
            }
        }

    11、对每一个假设进行断言,平均起来,每5行应有一个断言:
        object GetObject() { }

        public void myMethod()
        {
            object someObject = GetObject();

            //using System.Diagnostics;
            Debug.Assert(someObject != null);
        }

    12、只捕捉那些你自己能够显式处理的异常。

    13、如果在catch语句块中需要抛出异常,则只抛出该catch所捕捉到的异常(或基于该异常而创建的其他异常),这样可以维护原始错误所在的堆栈位置:
            catch(Exception exception)
            {
                MessageBox.Show(exception.Message);
                throw;//或throw exception;
            }

    14、避免自定义异常类;
        当自定义异常类是:
        a、让你自定义的异常类从Exception类继承;
        b、提供自定义的串行化机制;

    15、避免在一个程序集(assembly)中定义多个Main()方法。

    16、只把那些绝对需要的方法定义成public,而其它的方法定义成internal。

    17、避免让你的代码依赖于运行在某个特定地方的程序集。

    18、在applicationassembly(EXE client assemblies)中最小化代码量,使用类库来包含业务逻辑。

    19、枚举是一个指定的常数,其基类可以是除 Char 外的任何整型。如果没有显式声明基类,则使用 Int32。
       
        a、避免显式指定枚举的值:
           //正确:
           public enum Color
           {
               Red, Green, Bule
           }

           //避免:
           public enum Color
           {
               Red = 1, Green = 2, Bule = 3
           }

        b、避免为枚举指定一个类型:
           //避免:
           public enum Color : long
           {
               Red, Green, Bule
           }


    20、对于if语句,总使用一对{}把下面的语句块包含起来,哪怕只有一条语句也是如此。

    21、避免使用三元条件操作符。

    22、避免利用函数返回的Boolean值作为条件语句,把返回值赋给一个局部变量,然后再检测:

    23、总是使用以零为基数的数组;
        总是使用一个for循环显式的初始化一个引用成员的数组:
        public void MyMethod()
        {
            const int ArraySize = 100;
            MyClass[] array = new MyClass[ArraySize];
            for (int index = 0; index < array.Length; index++)
            {
                array[index] = new MyClass();
            }
        }

    24、使用属性来代替public或protected类型的成员变量。

    25、不要使用继承下来的new操作符,使用override关键字覆写new的实现。

    26、在一个非密封(non-sealed)类中,总是把那些public和proteced的方法定义成virtual。

    27、除非为了和其他语言进行互动,否则不要使用不安全(unsafe)的代码。

    28、避免显式类型转换,使用as关键字安全的转换到另一个类型:
        Dog dog = new GermanShepherd();
        GermanShepherd shepherd = dog as GermanShepherd;

        as 运算符类似于强制转换,所不同的是,当转换失败时,运算符将产生空,而不是引发异常。更严格地说,这种形式的表达式:
             expression as type
             等效于:
             expression is type ? (type)expression : (type)null
        只是 expression 只被计算一次。
        注意,as 运算符只执行引用转换和装箱转换。as 运算符无法执行其他转换,如用户定义的转换,这类转换应使用 cast 表达式来执行。

    29、使用代理(委托)推导而不要显式的实例化一个代理:
        delegate void SomeDelegate();
        public void SomeMethod() { }
        public void MyMethod()
        {
            SomeDelegate someDelegate = SomeMethod;
        }

    30、在调用一个代理前,总是检查它是否为null。

    31、不要提供public的事件成员变量,改用Event Accessor:
        public delegate void MyDelegate();
        public class MyPublisher
        {
            MyDelegate m_SomeEvent;
            public event MyDelegate SomeEvent
            {
               add
               {
                    m_SomeEvent += value;
               }
               remove
               {
                    m_SomeEvent -= value;
               }
            }
        }


    32、避免定义事件处理代理,使用EventHandler<T>或者GenericEventHandler。

    33、避免显式触发事件,使用EventsHelper安全的发布事件。

    34、总是使用接口;
        a、接口和类中方法和属性的比应该在2:1左右;
        b、避免只有一个成员的接口;
        c、努力保证一个接口有3-5个成员;
        d、不要让一个接口中的成员超过20个,而12则是更为实际的限制;
        e、避免在接口中包含事件;
        f、当使用抽象类的时候,提供一个接口;
        g、在类继承结构中暴露接口;
        h、推荐使用显式接口实现;
        j、从来不要假设一个类型支持某个接口,在使用前总是要判断一下:
           SomeType obj1;
           IMyInterface obj2;

           obj2 = obj1 as IMyInterface;
           if (obj2 != null)
           {
               obj2.Method1();
           }

    35、a、不要硬编码向用户显示的字符串,要使用资源。
        b、不要硬编码那些可能会随发布环境而变化的字符串,例如数据库连接字符串。
        c、使用String.Empty取代""。
        d、使用一个长字符串时,使用StringBuiler代替string。

    36、避免在结构中提供方法。
        a、参数化的构造函数是鼓励使用的;
        b、可以重载运算符。

    37、当声明了静态成员时,总是要提供一个静态构造函数。


    38、当早绑定(early-binding)可能时就尽量不要使用迟绑定(late-binding)。

    39、让你的应用程序支持跟踪和日志。

    40、a、除了要在switch语句块中实现代码跳转,不要使用goto关键字。
        b、总在switch语句的default情形提供一个断言:
            int number = SomeMethod();
            switch (number)
            {
                case 1:
                    Trace.WriteLine("Case 1:");
                    break;
                case 2:
                    Trace.WriteLine("Case 2:");
                    break;
                default:
                    Debug.Assert(false);
                    break;
            }
            (方法Debug.Assert(Boolean),检查条件,如果该条件为 false,则输出调用堆栈。)

    41、a、除了在一个构造函数中调用其它的构造函数之外,不要使用this关键字:
           public class MyClass
           {
               public MyClass(string message) { }
               public MyClass() : this("hello") { }
           }
        b、不要使用base关键字访问基类的成员,除非你在调用一个基类构造函数时和解决一个子类名称冲突时:
           public class Dog
           {
                public Dog(string name) { }
                virtual public void Bark(int howLong) { }
           }

           public class GermanShepherd : Dog
           {
                public GermanShepherd(string name) : base(name) { }
                public override void Bark(int howLong)
                {
                    base.Bark(howLong);
                }
           }

    42、不要使用GC.AddMemoryPressure()。

    43、不要依赖HandleCollector。

    44、总是在unchecked状态下运行代码(出于性能原因),但为了防止溢出或下溢操作,要果断的使用checked模式:
        int CalcPower(int number, int power)
        {
            int result = 1;
            for (int count = 1; count <= power; count++)
            {
                checked
                {
                    result *= number;
                }
            }
            return result;
        }

    45、使用条件方法来取代显式进行方法调用排除的代码(#if...#endif):
        public class MyClass
        {
            [Conditional("MySpecialCondition")]
            public void MyMethod() { }
        }

    46、a、不要在泛型接口中定义约束,接口级的约束通常可以利用强类型来替代:
           public class Customer { }

           //避免:
           public interface IList<T> where T : Customer { }

           //正确:
           public interface ICustomerList : IList<Customer> { }
        b、不要在接口上定义方法相关的约束。
        c、不要在代理上定义约束。
        d、如果一个类或方法提供了泛型和非泛型版本,那么优先选择泛型版本。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值