类-第二部分:常量和属性

<接上>

常量

常量与静态字段(静态量)很像。常量对类的每个实例都是可见的,没有实例,常量也可以使用。

但是,常量没有自己的存储位置,而是在编译时被编译器替换。静态量可以被改变,但常量一但声明就不可再改变。

静态常量分为成员常量本地常量。它们的区别是:成员常量是在方法中声明的,本地常量是在类中声明的。

常量在声明的时候必须赋值,并且除声明时以外不能在其它地方赋值。

与常量相似的还有readonly(只读属性),声明为readonly的对象像常量一样不能改变值,但它是在运行时被指派,而不是在编译时被指派。

有时也将const称为静态常量,将readonly称为动态常量。总结这几种常量的主要区别如下:

本地常量:在方法中声明,方法执行时创建,方法执行完毕即被销毁;

成员常量:在类中声明,在编译时被替换,始终存在,但不消耗内存;

以上两种常量称为静态常量,不能new,只能用部分类型;

只读常量:相当于类中的数据成员,可以是任意类型,可以在构造函数中赋值。

常量与静态量是两码事,不能同时声明const和static。


属性

属性是代表类中的或类的实例中的一个数据项的成员。使用属性的语法看起来与使用字段是相同的。

1
2
3
4
MyClass mc = new MyClass();

mc.myField = 5;        //这是字段
mc.MyProperty = 10;    //这是属性

如上,完全看不出来。但一般为了区分,属性的名字是首字母大写的,而字段是首字母小写。

属性与字段的共同点包括:

  • 它们都是命名的类成员;
  • 它们都有明确的类型;
  • 都可以被读取或赋值。

属性与字段的区别在于:

  • 属性是一个函数成员,字段是数据成员;
  • 由上可知,属性不为数据存储分配内存,它只是字段的“代理”;
  • 最主要的区别:属性可以执行代码。

属性的函数体中,包含setget两个方法。除此以外不能有其它方法,这两种方法有预定义的语法和语义,不能改变。但是,可以只使用其中之一,或者干脆都不用(那么就是一个没有意义的属性)。

声明属性的代码如下:

1
2
3
4
5
6
7
private int i; //字段用来存储数据,但外部不可直接访问

int MyValue    //属性可以访问函数中的私有字段
{
    set{ i = value; }
    get{ return i; }   
}

set和get,称为访问器。其中:

set访问器拥有一个单独的、隐形的值参value,是指调用该属性的set方法时传入的值,因此它也必然与属性的类型相同。

set访问器的返回类型是void。

get访问器没有参数。

get拥有与属性类型相同的返回类型,即调用属性的get方法时,得到与属性类型相同的返回值。

使用属性时,使用跟使用字段相同的语法,编译器会隐式调用访问器,不能显式的调用set或get访问器。

属性不分配内存,因此一般都要与字段配合使用。属性内可以做各种函数计算,只要在get中返回匹配类型即可。

一般来说,属性要声明为public,以供外部调用,而对应的实际字段声明为private,禁止外部直接访问。

只读或只写的属性

如果属性中只包含set访问器,那么该属性就是只写的,反之如果只包含get访问器,则属性是只读的。

通常来说,使用属性比直接使用公共字段要好得多,这是因为:

  • 属性是函数成员而不是数据成员,因此允许处理如何输入或输出;
  • 属性可以方便的设置为只读或只写;
  • 字段与属性在编译后语义不同;

自动属性

只需简单声明set和get即可自动声明属性。如下:

1
2
3
4
5
6
7
class C1
{
    public int MyProperty
    {
        set; get;
    }
}

VS中也提供了直接将字段封装为属性的快捷方式。

静态属性

属性可以声明为static,访问静态属性与其它静态对象是一样的,即:

  • 静态属性不能访问类的实例成员,只能访问静态成员,但可以被实例成员访问;
  • 不管是否创建类的实例,静态属性都存在;
  • 丛类的外部访问时,必须用类名,而不能用实例名。

<未完待续>接下来是构造函数

留言