• NET设计规范二:类型成员设计


    http://www.cnblogs.com/yangcaogui/archive/2012/04/20/2459567.html

    接着 → .NET设计规范一:设计规范基础 上一篇,我们来了解下类型成员命名的设计!

      3.类型成员命名的设计

        3.1字段

          ①遵循“ camelCasing  ”的命名规则

          ②要用名词或名词词组,不要使用C#关键字

          ③不要给字段添加任何前缀

          ④定义常量的时候要使用“PascalCasing ”的命名规范 

          ⑤当定义私有变量的时候使用“camelCasing”命名,并且在前面加上“_”作为前缀

        3.2方法

          ①必须为动词词组,不要使用C#关键字

          ②尽量根据方法对应的任务来命名,而不是根据内部一些实现细节来命名!

            常用的动词有:Get,Update,Delete,Add,Validate,Select,Search等等,这些动词后面加上你要做的内容,就构成了一个个方法名!

        3.3属性

          ①应该用名词或名词词组或形容词或形容词词组来命名,遵循“PascalCaing”大小写规范!

          ②不要让属性名与“Get”方法名相似

          

           这种情况说明属性应该是方法,应该合二为一,只定义一个方法!

          ③要使用肯定性的短语,如:CanSeek,而不是CantSeek

          ③如果属性的返回值是“bool”值,可以考虑为属性名添加“Is”,“Can”,“Has”等前缀!  

    1        public bool CanSeek { get; set; }
    2           public bool CantSeek { get; set; }  //不推荐
    3           public bool HasValue { get; set; }

          不过这种情况视情况而定,如果加了前缀反而使名称变的冗长了,那么就不要添加前缀了!

          

        3.4事件

          推荐文章:C# 中的委托和事件

          事件的设计个人认为是非常重要,所以我也很用心的学习了它.

          基本命名规则:

          ①要用动词或动词词组来命名

            如:Ckecked,Updated,Selected等等的动词或动词词组

          ②不要用“Before”或“After”等词语来表示前置事件或后置事件

          ③需要为事件定义一个参数信息实体,必须要以“EventArgs”后缀结尾

          ④要为绑定事件的方法名加上“On”前缀

           定义事件的基本的框架如下: 

     
     1     public class DemoSeven
     2     {
     3         public event EventHandler<UpdatedEventArgs> Updated;
     4         private UpdatedEventArgs _updatedEventArgs = new UpdatedEventArgs() { UpdatedID = "1234" };
     5         private EventHandler<UpdatedEventArgs> _updatedHandler;
     6 
     7         private const string str = "";
     8         private readonly string strOne = "";
     9 
    10         public void OnUpdated()  //执行事件的方法
    11         {
    12             _updatedHandler = Updated;
    13             if (_updatedHandler != null)
    14             {
    15                 _updatedHandler(this, _updatedEventArgs);
    16             }
    17         }
    18     }
    19 
    20     public class UpdatedEventArgs : EventArgs  //参数信息实体类
    21     {
    22         public string UpdatedID { get; set; }
    23     }
     

       

        3.5索引器

          其实说明白点索引器就是对集合或数组的封装.

          索引器的设计规则基本上都是固定的,都是使用“this”关键字的,如下:

     
    1         public string this[int index]
    2         {
    3             get { return ""; }
    4         }
    5 
    6         public string this[int index, string name]
    7         {
    8             get { return ""; }
    9         }
     

        3.6资源的命名

          可能在转换多国语言的时候会用到资源,那么资源里面参数的命名也变的很重要了!

          ①使用“PascalCasing ”命名方法,不要使用C#关键字

          ②要是名字具有描述性,而不是一味的把名字变短,当然也要保证名字的简短性,不过前提不能牺牲可读性

          ③尽量使用字母,数字和下划线

          ④要用点号来标识符清楚的划分层次

          

          ⑥对待异常信息要加上“Exception”的后缀

      如果大家都知道,就当复习咯!

      下一篇:.NET设计规范三:类型和类型成员设计的约定和惯用法

    .NET设计规范三:类型和类型成员设计的约定和惯用法

    继续上两篇未完成的工作 → ①.NET设计规范一:设计规范基础 ②.NET设计规范二:类型成员设计

      上两篇主要是说了类型和类型成员在命名上的规范,对它们的具体设计还没有涉及到,这篇文章是从一个普通开发人员的角度理解,会有很多不足之处,希望能得到大家的指点!

      首先说一下本文只是借助书本做的一些小结,大牛(架构师)们请不要喷我,如果实在憋不住,那就是使劲的喷吧,在喷中成长!

      4.类型设计的约定和惯用法

        4.1类和接口的选择

          ①应该优先使用类

          首先类是用于暴露抽象的优先选择!

          微软开发人员提供给我们的方案是:定义一个接口,然后再定义一个抽象基类实现这个接口!

    复制代码
     1     public interface IComponent  //这是.NET Framework中比较突出的案例
     2     {
     3         void GetID();
     4     }
     5 
     6     public class Component:IComponent
     7     {
     8         public void GetID()
     9         {
    10             // To Do.
    11         }
    12     }
    复制代码

          ②要用抽象类而不是接口来解除协定与实现之间的耦合

          ③如果需要定义一个多态的值类型层次结构的话,要定义一个接口

    复制代码
    1     public struct Int32 : IComparable, IFormattable, IConvertible
    2     {
    3         
    4     }
    5     public struct Int64 : IComparable, IFormattable, IConvertible
    6     {
    7 
    8     }
    复制代码

          ④考虑使用接口来实现多重继承

            Note:定义一个接口的标志就是它只做一件事。  

        4.2抽象类的设计  

          优点:

          ①灵活性比较大

          ②能通过继承扩展功能

          ③可以对抽象类中的虚方法和抽象方法实现重写达到功能扩展

          设计:

          ①抽象类中的构造函数修饰符因为为“protected”或者为“interal”,不过大多数情况都是“protected”

          ②定义好的抽象类必须要有类去继承它,而不能让它成为孤家寡人,这样有助于验证抽象类的有效性

    复制代码
    1     public abstract class Animal
    2     {
    3         protected Animal()
    4         {
    5         }
    6     }
    复制代码

         4.3接口的设计

          ①接口可以支持多重继承

          ②避免使用记号接口(也就是无成员的接口)

          ③要为接口提供实现的类型,跟上面抽象类一样,不要成为孤家寡人

          ④在大型项目开发中,都会提供一系列的接口供外部调用(这也是设计接口的场景之一)

          ⑤接口一旦定义就不能做改动了

        4.4静态类的设计

          ①尽量少自定义静态类,如果设计的静态类有一种辅助的效果,那么就应该定义一个这样的静态类,如.NET Framework中的“File”类,一种文辅助类

          ②不要在静态类中声明或覆盖实例成员

          ③要把静态类定义为密封的,抽象的,并添加一个私有的构造函数

        4.5结构的设计

          ①不要为结构提供默认的构造函数

          ②一般来说自定义的结构类比较少

        4.6枚举的设计

          ①要用枚举来加强那些表示值的集合的参数,属性或者返回值的类型型

          ②要优先使用枚举而不要使用静态变量

            比如:在定义一些颜色属性的时候,使用枚举是最好的选择。

          ③不要提供为了今后使用的枚举值

          ④不要定义枚举中只有一个值,如果只有一个那还不如定一个常量呢!

          ⑤要为简单的枚举提供“0”值,详细理解“0”值请看 → 从枚举的初始化说起 [C#]

    复制代码
    1     public enum Color
    2     {
    3         Red = 0,  //这是一种规范
    4         Yellow = 1,
    5         Black = 2
    6     } 
    复制代码

          ⑥考虑用“Int32”类型数值作为枚举值的值

          ⑦要使用复数名词或名词词组命名“标记枚举”,用单数名词或名词词组命名简单枚举

        4.7标记枚举

          标记枚举提供对枚举值的位操作!

          ①必须要加上“[Flags]”标志特性

          ②要用2的幂次方作为标记枚举的值(其实这个规则不怎么明白,不过这确实是一个很重要的规范)

    复制代码
    1     [Flags]
    2     public enum MyEnumTypes
    3     {
    4         Created = 0x0002,
    5         Updated = 0x0004,
    6         Deleted = 0x0008
    7     }
    复制代码

           ③在合适的情况下要为标记枚举提供特殊的枚举值,也就是组合枚举

    复制代码
    1     [Flags]
    2     public enum FileAccess
    3     {
    4         Read = 1,      //这边定义的“int”型的枚举值跟上面使用2的幂次方作为枚举值没有冲突,我们应该在以后的开发中使用2的幂次方作为枚举值
    5         ReadWrite = 3,  //提供一个组合值,或者这样 →  ReadWrite = Read | Write
    6         Write = 2
    7     }
    复制代码

           ④不要定义无效的枚举值

      5.成员设计

        5.1方法的重载

          ①避免在重载的时候随意给参数名,应该保持参数名的一致性

          

          ②避免打乱参数的顺序,在多个重载中保持参数顺序的一致性

          ③要把最长的重载做成“虚方法”,这样有助于派生类的重写,增强了扩展性

          ④不要在重载成员中使用“ref”或“out”参数

    View Code

          ⑤要允许引用类型的参数可为“null”,不过需要在方法中对“null”值进行判断

        5.2显式和隐式实现接口

          ①避免显式实现接口

            感觉这个规范在“迭代器”中的运用还是比较多的,可以参照这篇文章:程序猿个人文章目录索引中的迭代器系列

            说实话这个话题我也不敢讲多少,因为我自己对它本质的东西理解的好不够深入,所以就泛泛的说几句!

        5.3属性和方法的选择

          ①属性侧重于数据的体现,而方法侧重于操作,不过话说两者的性能不是很多(虽然书上也讨论过两者性能差异,但是可以忽略不急)

          ②建议多使用属性,如果定义够多的属性,那么相应的就要为属性定义同等的私有变量,也就是对变量的封装

          ③避免方法中参数过多,如果太多建议使用属性来减少方法重载

          ④需要使用方法的一些通用情况

            I,该操作是一个转化操作,如:ToString()方法

            II,该操作每次返回的结果不一样,如:Guid.NewGuid()

            III,该操作返回的是一个数组或集合(这个情况还是蛮实用的)

          ⑤所以说使用属性是它只代表简单的数据操作,过于复杂的操作应该使用方法来完成 

        5.4索引器的设计

          个人理解:索引器就是对集合以及数组的封装!

          索引器可以是单个索引也可以是多个索引,索引器是附加在类级别上的,所以它才使用“this”关键字的,在前面一文中也简单的介绍了这方面的知识!

          ①避免使用一个以上参数的索引器

        5.5构造函数设计

          有两种构造函数:类型构造函数和实例构造函数

          类型构造 → 也就是静态构造函数,必须为静态的,在进行初始化的时候是第一个执行的!

          ①必须为私有构造(编译器会强制规定的)

          ②不要在类型构造中抛出异常

          实例构造 → 也就是普通的构造

          ①考虑提供简单的构造函数,可以默认构造函数

          ②如果使用构造函数重载,那么构造函数的参数作用应该设置为主要属性,而不是“可有可无”的参数

          ③要在构造函数做最少的事

          ④如果要使用构造函数重载,需要提供一个空构造,这样就不会破坏依赖于空构造的类型成员

        5.6事件的设计

          关于事件定义的基本规范可以参考前一篇的文章!

          ①要使用系统自定义的委托 →  EventHandler<T> (可以说这是个通用规范把)

          ②考虑把事件的处理方法设置为虚方法,这样派生类就可以重写,提高扩展性

          如果想深入理解推荐几篇文章:C#委托和事件(2) ,浅谈C#中常见的委托C# 中的委托和事件

        5.7字段的设计

          ①不要提高公共的或受保护的实例字段

          ②要使用属性来访问字段,这样跟直接访问字段是一样的

          ③要用常量字段来表示永远不会改变的常量,大家可以找点资料理解下“const”和“readonly”的差异

          ④不要把可变类型的实例赋值给只读字段

          ⑤要用公有的静态只读字段来定义预定义的对象实例(这个个人理解起来有点不懂)

          

      好了就写这么多了,感觉好累,因为本人不是啥架构师,是个小菜鸟(这是从我这个角度看问题的,高度还没有上升上去),写这些东西也是模仿书上的,算是一点小总结,不能算经验的!

      如有问题还请大家多多指教!

      下一篇:.NET设计规范四:简单的扩展设计与个人思考

    .NET设计规范四:简单的扩展设计与个人思考

    有一个星期没有写文章记录学习与工作之路了,今天趁着是五四青年节下午休息的时光写了.NET设计规范的最后一篇了!

      在做好一系列的命名规范,设计规范之后,更高层的规范就是那些扩展性的规范了(或者说是面向对象,其实这方面我是菜菜鸟),这里我只简单的说说!

      说实话写这样的文章真不好写,尤其是涉及到架构方面的设计我更是无从下手,所以我就把书本上的总结一下,尽量少一点个人想法!

      接着上三篇:①.NET设计规范一:设计规范基础  ②.NET设计规范二:类型成员设计  ③.NET设计规范三:类型和类型成员设计的约定和惯用法

      5.扩展性设计

        5.1密封类

          ①不推荐使用密封类,除非有特殊的理由

        5.2抽象类和抽象接口

          ①必要的时候应该定义一个抽象类(或者是一个基类)和一个接口,然后用抽象类(或基类)实现这个接口      

          

        5.3基类

      6.异常的设计

        6.1自定义异常的设计

          ①避免太深的继承层次

          ②必须要从“System.Exception”派生出新的异常类,这是个规范

          ③要在异常类名称后面加上“Exception”后缀

          ④要是的异常可以序列化,这是为了能够跨应用程序和跨平台

          ⑤要为异常提供常用的构造函数

          

          ⑥要定义“ToString”方法返回异常信息

          ⑦书中的两点建议,不怎么明白

          

    复制代码
     1     [Serializable]
     2     public class MyException:Exception  //这是最简单的异常处理信息
     3     {
     4         private string _message;
     5 
     6         public MyException()
     7         {}
     8         public MyException(string message)
     9         {
    10             _message = message;
    11         }
    12 
    13         public override string ToString()
    14         {
    15             // TO DO.
    16             return "";
    17         }
    18     }
    复制代码

          PS:书中对异常的介绍写了很多,可是理解的很少,这里就把自己的理解写了下来,所以还需要在看几遍,这样才能慢慢的理解他!  

      7.数组,特性,集合的编码规范

        7.1数组

          ①优先使用集合而不是数组

          ②不要把数组设计为只读数组,应该使得用户可以修改数组中的元素

        7.2Attribute(特性)

          ①命名时要添加“Attribute”后缀,并且继承“Attribute”基类

            public class MyAttribute:Attribute

          ②要在自定义的时候使用“AttributeUsageAttribute”这个特性 

    复制代码
    1     [AttributeUsage(AttributeTargets.All)]
    2     public class MyAttribute : Attribute
    3     {
    4 
    5     }
    复制代码

          ③要为可选参数提供可设置的属性 

          

          ④要为必填参数提供只读属性

          ⑤要提供构造函数对必填参数进行初始化,每个参数名应该与相应的属性名一样(可能大小写会不一样)

    复制代码
     1     [AttributeUsage(AttributeTargets.All)]
     2     public class MyAttribute : Attribute
     3     {
     4         public MyAttribute(string name, string message)
     5         {
     6             Name = name;
     7             Message = message;
     8         }
     9 
    10         private string Name { get; set; }    //这是必填参数
    11         private string Message { get; set; }  //这是必填参数
    12         public string Author { get; set; }   //这是可选参数
    13     }
    14 
    15     [My("ss", "ss", Author = "sss")]  //那么我在调用时就会出现如下调用方式
    16     public class One
    17     { }
    复制代码

          ⑤尽可能把自定义的Attribute密封起来,这样会是的查找“Attribute”更快

          ⑥避免提供构造函数对可选参数进行初始化

          ⑦避免对自定义的“Attribute”构造函数进行重载

        7.3关于集合属性和返回值

          ①不要提供可设置的集合属性 

    复制代码
    1         public Collection<String> Items { get; set; }  //坏的设计
    2         public Collection<string> Items          //提倡的设计
    3         {
    4             get
    5             {
    6                 // TO DO  
    7             } 
    8         }
    复制代码

          ②要用“Collection<T>”或其子类作为属性或返回值来表示可读写的集合(就像上面一样)

          ③使用“ReadOnlyCollection<T>”作为属性或返回值来表示只读集合

      这篇文章写的不好,可能真的是由于本人知识积累的有限,写的很艰难,不过最终还是写好了,继续加油把!

  • 相关阅读:
    最艰难的采访IT公司ThoughtWorks代码挑战——FizzBuzzWhizz游戏
    SQL Server 存储字符数较大字段的问题
    c# var的含义与用法
    ListBox和ComboBox绑定数据简单例子
    “C# 未在本地计算机上注册microsoft.Jet.OLEDB.12.0”的解决方案
    [转] c# 操作Word
    C++ Regsvr32订购具体解释
    数字计算的有序排列的号码出现二分法
    合作信息处理模型
    内存四个领域,变量声明和定义,注册,c内联汇编,auto,堆,不变,静态变量
  • 原文地址:https://www.cnblogs.com/123ing/p/4051369.html
Copyright © 2020-2023  润新知