一、什么是类
类的定义
class Person //默认修饰符是internal,表示仅在当前项目内可被访问
{
//Class members
}
类访问修饰符
注意:
(1). 在C#中只能有一个基类,如果继承了一个抽象类,则必须实现所继承的所有抽象成员(除非派生类也是抽象的)
(2). 派生类的访问性不可高于基类
(3). 除了继承基类还可以继承接口,接口可以继承多个,但两者都存在时,用逗号隔开且基类必须放置在前
二、类的成员
类的成员包含:字段、属性、方法和构造函数等
类成员访问修饰符
字段 (访问修饰符 字段类型 字段名称)
class Person
{
private readonly string name;
public const int age;
protected bool sex;
public static double height;
}
可以使用关键字readonly和const来定义字段
readonly修饰字段不需要在定义时初始化,而是可以在构造函数中再完成初始化
const修饰字段必须在定义时进行初始化
使用关键字static来声明字段,则必须通过类来访问Person.height
属性(用来对字段进行灵活控制和访问)
public string Name
{
//get访问器
get
{
return name;
}
//set访问器
set
{
//value是隐式参数
name = value;
}
}
当属性仅包含get访问器,或set访问器为private级别时,称为只读属性
当属性仅包含set访问器,或get访问器为private级别时,称为只写属性
属性除了能访问私有字段外,还可以根据需要加入更多的逻辑控制代码
public int Age
{
//get访问器
get
{
return age;
}
//set访问器
set
{
//在set访问器中添加更多的逻辑代码
if( value < 0 || value > 120 )
{
throw(new ArgumentOutOfRangeException("AgeIntPropery",value,"年龄必须在0~120之间"));
}
age = value;
}
}
属性也可以声明为静态属性
方法
public void Print( string name )
{
Console.WriteLine( "输入的值为: " + name );
}
//方法重载
public void Print( string name, int age )
{
Console.WriteLine( "输入的值为: {0},{1}", name, age );
}
构造函数(为对象分配内存空间,并初始化类的成员)
1.实例构造函数
实例构造函数用于创建和初始化类的实例。使用new运算符创建对象的过程,其实就是在调用实例构造函数,来初始化类中所有实例成员。
public Person( )
{
name = "Andy";
}
public Person( string name)
{
this.name = name;//this代表当前类的实例对象
}
构造函数具有如下特点:
(1). 构造函数可以进行方法重载。实现了方法重载,就可以通过不同的方式来完成类的实例化。
(2). 如果没有为类显示地定义一个构造函数,则C#编译器会自动生成一个函数体为空的默认无参的实例构造函数。
(3). 构造函数必须和类同名,且不允许有返回类型。
使用private关键字修饰的构造函数称作私有构造函数
如果只定义了一个或多个私有构造函数,而没有其他公共构造函数,则其他类不能调用该类的私有构造函数来创建类的实例。私有构造函数的典型应用是:设计模式中的单例模式的实现。
//下面的实现也是设计模式中的单例模式的实现
private Person( )
{
Console.WriteLine( "私有构造函数被调用!" );
name = "Andy";
}
private static Person _Instance = new Person( );
public static Person Instance( )
{
return _Instance;
}
调用:
class Program
{
static void Main( string[ ] args )
{
//通过调用Instance()静态方法来返回一个Person实例
//此时不能使用new运算符来创建实例
//即不能使用Person person = new Person()的代码来创建实例
Person person = Person.Instance( );
Console.WriteLine( "类实例的Name属性为: {0}", person.Name );
Console.ReadKey( );
}
}
2.静态构造函数
静态构造函数用于初始化类中的静态成员,在创建第一个实例或引用任何静态成员之前,CLR都将自动调用静态构造函数。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example_class
{
class Person
{
//静态构造函数,仅执行一次
static Person( )
{
Console.WriteLine( "静态构造函数被调用!" );
name = "Andy";
}
private static string name;
public static string Name
{
//get访问器
get
{
return name;
}
//set访问器
set
{
name = value;
}
}
}
class Program
{
static void Main( string[ ] args )
{
Console.WriteLine( Person.Name );
Console.WriteLine( "---------" );
Console.WriteLine( Person.Name );
Console.ReadKey( );
}
}
}
运行结果:
静态构造函数特点:
(1). 静态构造函数不能使用任何访问修饰符
(2). 静态构造函数不能带有任何参数
(3). 静态构造函数只会执行一次
(4). 不能直接调用静态构造函数
(5). 在程序中,程序员无法控制执行静态构造函数的时机
析构函数(用于在类销毁之前释放类实例所使用的托管和非托管资源)
对于C#应用程序所创建的大多数对象,可以依靠.NET的垃圾回收器来隐式地执行内存管理任务。但若创建封装了非托管的对象,在应用程序使用完这些非托管资源之后,垃圾回收器将运行对象的析构函数(即Finalize方法)来释放这些资源。
//析构函数
~Person( )
{
Console.WriteLine( "析构函数被调用了!" );
}
该析构函数隐式地调用了基类object的Finalize方法。
析构函数特点:
(1). 不能在结构体中定义析构函数,只能对类使用析构函数
(2). 一个类只能有一个析构函数
(3). 无法继承或重载析构函数
(4). 无法显示地调用析构函数,析构函数是由垃圾回收器自动调用的
(5). 析构函数既没有修饰符也没有参数
索引器
作用:当一个类包含数组成员时,索引器的使用将大大地简化对类中数组成员的访问。
索引器的定义类似于属性,也具有get访问器和set访问器,定义形式如下:
[修饰符] 数据类型 this[索引类型 index]
{
get{//返回类中数组某个元素}
set{//对类中数组元素赋值}
}
说明:
(1). 数据类型是类中要存取的数组的类型
(2). 索引类型表示该索引器使用哪一个类型的索引来存取数组元素,可以是整形,也可以是字符串类型
(3). this则表示所操作的是类对象的数组成员,可以简单地把它理解为索引器的名字(注意,索引器不能自定义名称)
class Person
{
//可容纳10个整数的数组
private int[ ] intarray = new int[ 10 ];
//索引器的定义
public int this[ int index ]
{
get
{
return intarray[ index ];
}
set
{
intarray[ index ] = value;
}
}
}
以上代码定义了一个索引器,索引器可以让我们像访问数组一样访问类中的数组成员,下面演示如何使用索引器:
class Program
{
static void Main( string[ ] args )
{
Person person = new Person( );
//通过索引器对类中的数组进行复制
person[ 0 ] = 1;
person[ 1 ] = 2;
person[ 2 ] = 3;
Console.WriteLine( person[ 0 ] );
Console.WriteLine( person[ 1 ] );
Console.WriteLine( person[ 2 ] );
Console.ReadKey( );
}
}
运行结果:
三、类实例化
需要先声明一个该类类型的变量,然后使用new运算符后跟实例构造函数类完成实例化。类的实例对象是对类的具体化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example_class
{
class Person
{
private string name;
private bool sex;
public string Name
{
get;
set;
}
public bool Sex
{
get;
set;
}
public Person( string name, bool sex )
{
this.name = name;
this.sex = sex;
}
}
class Program
{
static void Main( string[ ] args )
{
//实例化两个类对象
Person person1 = new Person( "张三", true );
Person person2 = new Person( "李四", true );
Console.ReadKey( );
}
}
}
注意:只有包含实例构造函数的类才能被实例化,而在静态类中是不能定义实例构造函数的。
四、类与结构体的区别
(1). 语法上的区别在于,定义类要使用关键字class,而定义结构体则使用关键字struct。
(2). 结构体中不可对声明字段进行初始化,但类可以。
(3). 如果没有为类显示地定义构造函数,C#编译器会自动生成一个无参数的实例构造函数,我们称为隐式构造函数;而一旦我们显示地定义了一个构造函数,C#编译器就不会自动生成隐式构造函数了。但是,在结构体中,无论你是否显示地定义了构造函数,隐式构造函数都是一直存在的。
(4). 结构体中不能显示地定义无参数的构造函数,这也说明无参构造函数是一直存在的,所以不能再显示地为结构体添加一个无参数的构造函数;而类中则可以显示地定义一个无参数的构造函数。
(5). 在结构体的构造函数中,必须要为结构体中的所有字段赋值。
(6). 创建结构体对象可以不使用new关键字,但此时结构体对象中的字段是没有初始值的;而类必须使用new关键字来创建对象。
(7). 结构体不能继承结构或者类,但可以实现接口;而类可以继承类但不能继承结构,它也可以实现接口。
(8). 类是引用类型,而结构是值类型
(9). 结构体不能定义析构函数,而类可以有析构函数
(10). 不能用abstract和sealed关键字修饰结构体,而类可以