Effiective C# Item1 : 使用属性代替成员变量

    Item1:Always Use Properties Instead of Accessible Data Members

    属性是C#语言中一个很重要的特性,我们可以使用属性对成员进行封装。

    从编译器的角度来看,属性就是针对成员变量两个方法:get_xxx和set_xxx,这一点和Java是很像的,当我们在Java中定义个成员变量,然后通过重构生成相应的属性时,对应的方法名就是get_xxx和set_xxx。

    为什么要使用属性来代替成员变量呢?我认为从类的职责划分的角度进行理解会更好一些,当一个类向外公开一个访问入口时,这个入口可以是公开的方法、属性或者成员变量,那么从封装变化的观点来看,类本身应该对自身变量的异常进行处理,而不是由调用方进行处理。因此,如果是坚持使用公开的成员变量,那么对变量的异常处理,只能由调用方来进行处理,这样做是不合理的。一方面,同样的异常处理在多个调用方进行,会出现大量的重复代码,另一方面,当业务发生变化,成员变量的逻辑有改变时,需要修改每个调用该变量的地方,这将会是一件令人非常抓狂的事情。

    使用属性代替成员变量,有以下好处:

  1. 可以在set或者get中对异常情况进行统一处理,或者可以在set和get中对多线程进行统一处理。
  2. 可以通过设置set和get的方式将属性置为可读写的,也可以通过只设置get不设置set的方式,将属性置为只读的,这样可以避免调用方对属性的值进行错误的赋值。
  3. 由于set和get可以看做是方法的形式,那么它们就可以使用方法的访问限制符,例如可以将set设置为private,将get设置为public,这样,对于属性来说,它的调用方还是不能为其赋值,从另外的角度实现了只读属性。当然还可以使用其他限制符,例如protected、internal等。
  4. 可以在接口中声明属性,也可以在抽象类中声明抽象属性。这样在进行框架设计时,可以为具体业务留出足够的空间。
  5. 我们可以对属性的外延进行扩充,进而讨论索引器,索引器的形式:this[int i]{set;get},索引器也包括set和get,同时"[]"中可以是数字,也可以是其他字符串。当我们通过索引器进行数据绑定时,要求"[]"中必须是数字。

    使用属性会降低程序的性能吗?

    一般来说,是不会的,首先,.NET程序运行时,是采用JIT的方式进行的,如果会影响性能,那么只能是在第一次运行的时候;其次,编译器在对属性进行编译时,会采用内联函数的方式,对set和get进行处理,这样的结果,和直接访问数据成员差别很小,基本可以忽略不计。

    注意:当我们将类中公开的成员变量重构为属性后,需要重新编译所有使用到这个属性的类,因为这个重构的操作破坏了二进制的兼容性。

posted @ 2010-01-03 00:00  李潘  阅读(1260)  评论(0编辑  收藏  举报