C#中的域(Field)和属性(Property)
(一般的命名习惯 field: _xxx 对应的属性: xxx)
或许狭义地进行区分一下,Get和Set的实现的称为属性,其他的变量称为数据成员。
C#将属性从其他语言中的一种特殊约定提升成为一种第一等(first-class)的语言特性。属性在使我们可以将数据成员暴露为公有接口的同时,还为我们提供了在面向对象环境中所期望的封装。在C#中,属性(property)是这样一种语言元素:它们在被访问的时候看起来好像是数据成员,但是它们却是用方法实现的。
.NET框架类库(Framework Class Library)的设计者们认为将数据成员直接暴露给外界不符合面向对象的设计原则,因为属性不表示存储位置,这是属性和域的根本性的区别。.NET框架类库这样的设计策略从某种意义上讲也是在推动我们遵循面向对象的设计原则。
例如,我们可能很快就会发现Customer类不能有一个空的Name。如果我们使用一个公用属性来实现Name,那么只需要在一个地方做更改即可:
public class Customer
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (( value == null ) ||( value.Length == 0 ))
{throw new ArgumentException( "Name cannot be blank","Name" );}
_name = value;
}
}
// ……
}
如果使用的是公有数据成员,我们就要寻找并修改所有设置Customer的Name的代码,那将花费大量的时间。
这里的value是C#的关键字,是我们进行属性操作时的set的隐含参数,也就是我们在执行属性写操作时的右值。
在AS3中,
访问控制符 function get 方法名():返回类型{
//其他代码;
return 要访问的私有属性;
}
访问控制符 function set 方法名(参数:参数类型):void{
//其他代码;
要访问的私有属性 = 参数; //参数的类型要与该私有属性的类型一致
}
C#中的域(Field)和属性(Property)
访问一个类的成员变量可以有两种方式:域、属性。域作为Public类型的成员变量访问,而属性不能直接进行访问,必须通过访问器(Assessors)进行。
域(Field)
l 域表示与对象或类相关联的变量。
l 域的声明中如果加上了readonly修饰符,表明该域为只读域。对于只读域我们只能在域的定义中和它所属类的构造函数中进行修改。在其他情况下,域是“只读”的。
l static readonly的作用和#define、const的作用类似。区别是:const型表达式的值是在编译时形成的,而static readonly表达式的值直到程序运行时才形成。如:
Public class A
{
Public static readonly int X = 1;
}
l C/C++中未经初始化的变量是不能使用的。在C#中,系统将为每个未经初始化的变量提供一个默认值。对于所有引用类型的变量,默认值是null。所有值类型的变量的默认值是固定的。对于静态域,类在装载时对其进行初始化;对于非静态域,在类的实例创建时进行初始化。在默认的初始化之前,域的值是不可预测的。
例如下面的代码是合法的:
class Test
{
static int a = b+ 1;
static int b = a+ 1;
}
实际上等价于:a = 1; b = 2;
而下面的代码则是非法的:
class A
{
int x = 1;
int y = x + 1;
}
因为非静态变量x在类A实例化以前并没有初始化,代码y = x + 1无法得到正确的x的值。
属性(property)
l 充分体现了对象的封装性:不直接操作类的数据内容,而是通过访问器进行访问,即借助于get和set对属性的值进行读写;另一方面还可以对数据的访问属性进行控制(当然也可以通过对普通域加readonly关键字来实现。
l 设计原则:属性封装了对域的操作。把要访问的域设为private,通过属性中的get和set操作对域进行设置或访问。
l 不能把属性作为引用类型或输出参数来进行传递。
l get方法没有参数;set方法有一个隐含的参数value。除了使用了abstract修饰符的抽象属性,每个访问器的执行体中只有分号“;”外,其他的所有属性的get访问器都通过return来读取属性的值,set访问器都通过value来设置属性的值。
l 采用间接方式来访问对象的属性(间接调用get、set方法):对象.属性 = 值(调用set),变量 = 对象.属性(调用get)。 <John: 而属性是对某个域的读写>
l 在属性的访问声明中:
只有set访问器,表明该属性是只写的。
只有get访问器,表明该属性是只读的。
既有set访问器,又有get访问器,表明该属性是可读可写的。
举例:通过属性访问器访问类的属性。
using System;
public class File
{
private string s_filename;
public string Filename
{
get
{
return s_filename;
}//get
set
{
if(s_filename!=value)
{
s_filename = value;
}//if
}//set
}//Filename
}