一、类
类包括:字段(用来存储数据)、属性(用来保护字段,属性的本质是两个函数get和set)、构造函数(用来初始化对象,给对象的每一个属性赋值)、函数(描述对象的行为)、索引器(以索引的方式去访问对象)。
一个类都可以包含两种成员:字段(Field)与方法(Method)。
字段即变量,方法即函数。
类的字段一般代表类中被处理的数据,类的方法大多代表对这些数据的处理过程或用于实现某种特定的功能,方法中的代码往往需要访问字段保存的数据。
声明为public 的变量和函数可以被外界直接访问,与此对应,private 的变量与函数,则为类的私有成员,只能由类自己使用。
二、字段(变量)
字段(Field)代表了类中的数据,在类的所有方法之外定义一个变量即定义了一个字段。在变量之前可以加上public、private 和protected 表示字段的访问权限。以下代码展示了在类Student 中定义的两个公有字段Age 和SN,外界可以通过类Student 创建的对象来读取或设置这两个字段的值。
可以在定义字段的同时给予一个初始值,如下所示:
三、方法(函数)
一个C#函数:
返回值类型 方法名(参数列表)
{
语句1;
语句2;
//…
return 表达式;
}
例:函数需要向外界返回一个值,由return 语句实现。
int Add(int x, int y)
{
return x + y;
}
放在一个类中的函数(通常附加一个存取权限修饰符如public 和private)称为“方法(method)”。
如果一个函数没有返回值或不关心其返回值,则将其返回值定义为void。
void f() //不返回任何值的函数
{
语句1;
语句2;
//…
return ; //在return后写一个空语句
}
四、方法的定义与使用
访问一个方法的最基本方式是通过类创建的对象。
public class MathOpt
{
public int Add(int x, int y)
{
return x + y;
}
}
class Program
{
static void Main(string[] args)
{
//创建MathOpt类的对象
MathOpt obj = new MathOpt();
//通过对象调用类的方法,结果保存在局部变量中
int result = obj.Add(100, 200);
}
}
五、方法的重载
两个构成重载(Overload)关系的函数必须满足以下条件:
(1)函数名相同。
(2)参数类型不同,或参数个数不同。
需要注意的是,函数返回值类型的不同不是函数重载的判断条件,另外,C#是区分大小写的语言。
class MathOpt
{
//整数相加
public int Add(int x, int y)
{
return x + y;
}
//浮点数相加
public double Add(double x, double y)
{
return x + y;
}
}
重载函数的调用:
MathOpt mathobj = null; //定义MathOpt对象变量
mathobj = new MathOpt(); //创建对象
int IResult=mathobj.Add(100, 200); //调用类的整数相加方法
double FResult = mathobj.Add(5.5, 9.2); //调用类的浮点数相加方法
Console.WriteLine("100+200=" + IResult ); //输出结果
Console.WriteLine("5.5+9.2=" + FResult ); //输出结果
传给方法的实参为整数时,调用参数类型为int 的Add(int,int)方法,传给方法实参为浮点数时,将调用参数类型为double 的Add(double , double)方法。
六、类的静态成员
如果在声明时没有加“static”关键字,则称之为类的“实例方法(instancemethod)”。加了static 关键字的方法称为“静态方法(static method)”。
加了static 关键字的字段称为“静态字段(static field)”。
静态方法在使用时不需要创建对象,而是按以下格式直接调用:
例:计算2的3次方
double ret = Math.Pow(2, 3);//,.NETFramework 将常用的数学函数放到了类Math 中
类的实例方法可以直接访问类的公有静态字段,比如数学常数π 就是Math 类的公有静态字段,可以被用来计算圆周长:
//计算圆周长
double GetPerimeterOfCircle(Double radius)
{
return 2 * Math.PI * radius;
}
区分静态成员与实例成员的典型例子:
class StaticMembers
{
public static int staticVar=0; //静态字段
public int dynamicVar=0;
public void increaseValue()
{
staticVar++;
dynamicVar++;
}
}
以下是测试代码:
static void Main(string[] args)
{
StaticMembers obj=null;
//创建100个对象
for (int i = 0; i < 100; i++)
{
obj = new StaticMembers();
obj.increaseValue();
}
//查看静态字段与普通字段的值
Console.WriteLine("dynamicVar=" + obj.dynamicVar);
Console.WriteLine("staticVar=" + StaticMembers.staticVar);
//程序暂停,敲任意键继续
Console.ReadKey();
}
程序的运行结果:
dynamicVar=1
staticVar=100
因为类的静态成员拥有以下特性:
类的静态成员是供类的所有对象所共享的。
在本节示例中创建了100 个对象,每个对象拥有1 个dyanmicVar 字段,一共有100 个dyanmicVar 字段,这些字段是独立的,“互不干涉内政”。而staticVar 字段仅有一个,为所
有对象所共享。因此,任何一个对象对staticVar 字段的修改,都会被其他对象所感知。
类实例成员与静态成员的访问规则:
① 位于同一类中的实例方法可直接相互调用。
② 类的字段(包括实例字段和静态字段)可以被同一类中的所有实例方法直接访问。
③类中的静态方法只能直接访问类静态字段。
上述规则中,需要特别注意在静态方法中直接调用类的实例方法是非法的。
例如以下代码将无法通过编译。
class StaticMembers
{
public static int staticVar=0; //静态字段
public static void staticFunc() //静态方法
{
increaseValue(); //静态方法中不能调用实例方法×
dynamicVar++; //静态方法中不能访问实例字段×
staticVar++; //静态方法可以访问静态字段正确!
}
public int dynamicVar=0;
public void increaseValue()
{
staticVar++;
dynamicVar++;
}
}
那么,如何在静态方法中访问实例数据?
很简单,可以在静态方法中创建对象,通过对象来访问即可。将静态方法staticFunc()修改如下即可通过编译:
public static void staticFunc() //静态方法
{
//在静态方法中通过对象访问类的实例成员
StaticMembers obj = new StaticMembers();
obj.increaseValue(); //调用实例方法,OK!
obj.dynamicVar++; //访问实例字段,OK!
}
七、类的属性是一种特殊的“字段”。
在设计类时使用属性(Property)可以保证只有合法的数据可以传给对象。
例:
class Student
{
private String _Name="姓名默认值";//定义一个私有的_Name 字段
public String Name//定义一个Name 属性
{
get //读
{
return _Name;
}
set //写,使用隐含变量value
{
if (value.Length == 0)
throw new Exception("名字不能为空");
_Name = value;
}
}
}
{
static void Main(string[] args)
{
Student stu = new Student();
Console.WriteLine("请输入姓名");
string value = Console.ReadLine();
stu.Name = value;
Console.WriteLine(stu.Name);//或Console.WriteLine(value);
Console.ReadKey();
}
}
编写属性的方法如下:
(1)设计一个私有的字段用于保存属性的数据;
(2)设计get 读访问器和set 写访问器存取私有字段数据。
C#中还允许定义只读属性和只写属性。
八、构造函数(constructor)
当使用new 关键字创建一个对象时,构造函数被自动调用。在C#中,类的构造函数与类名相同,没有返回值。
class A
{
//类A的构造函数
public A()
{
}
}
类的构造函数在以类为模板创建对象时被自动调用。构造函数一般用于初始化类的私有数据字段。