——类
访问权限
public:所有类都可以访问,包括其他程序集
private:只有该类自己可以访问。
protected:只有继承该类的派生类可以访问,包括其他程序集的派生类。
internal:程序集内,都可以访问。
protected internal:程序集内,都可以访问,并且其他程序集的派生类也可以访问。
类的访问权限
类只有public和internal两种访问权限修饰符,internal只允许程序集内可见。
静态字段和静态函数
静态字段和静态函数都通过类名调用,并且静态函数中无法访问实例成员,只能访问静态成员。
常量
类中字段常量和静态字段类似,都可以在类不实例化的情况,通过类型调用。不过与静态字段不同的是,常量没有自己的存储位置,在编译时被编译器替换。并且常量不允许设置为static。
属性
属性属于函数成员。
属性的get和set访问器不可以显示使用,只能隐示使用。
属性的另个访问器必须有一个,否则会报错。
属性也可以声明为静态,表示静态的函数成员,和静态方法的用法基本一样。
构造函数
构造函数用来初始化实例的状态,如果声明为public,表示允许在类外部实例化,构造函数不允许有返回值。如下,构造函数在函数体内初始化类的实例成员,前提是这些程序是public静态构造函数
静态构造函数会初始化类的静态字段。
静态构造函数由系统会自动调用。
它的调用在引用任何静态成员之前,在创建类的任何实例之前(也就是说会在普通构造函数之前)。
一个类只能有一个静态构造函数,并且不能有参数,也不能有访问修饰符。
不能访问所在类的实例成员。
readonly
表示只读的,它的效果和const效果一样,不过readonly更像是把变量标注为只读。
const需要在声明语句中初始化,而readonly可以在声明语句初始化,也可以在构造函数中初始化,都不可以在函数成员中初始化
const的值只能在编译时决定,而readonly可以再运行时决定。
const总是静态的,readonly可以是实例,也可以用static修饰为静态,
const在内存中没有存储位置,readonly有存储位置。
this关键字
this关键字在类中使用,用来引用当前的实例,相对的,它无法引用静态字段;同时由于静态函数成员无法使用实例成员,因此this关键字无法在静态函数成员中使用。
this关键字的主要作用就是区分成员和本地变量。
索引器
索引器可以让我们以数组访问的行书对实例的成员字段进行操作,索引器跟属性很类似,可以说属性是为一个数据成员提供get和set,索引器为多个相同类型的成员提供get和set。
它有许多和属性一样的性质,不过,它不能声明为static。
下面是一个索引器的例子
class QuickSort
{
private string str1;
private string str2;
private string str3;
//注意,与属性不同的是,索引器没有名字,使用this关键字,后面跟上中括号,里面是一个索引
public string this[int idx]
{
set
{
switch (idx)
{
case 0: str1 = value; break;
case 1: str2 = value; break;
case 2: str3 = value; break;
default:
break;
}
}
get
{
switch (idx)
{
case 0: return str1;
case 1: return str1;
case 2: return str1;
default:
return null;
}
}
}
下面是使用这个索引器
QuickSort sort = new QuickSort();
sort[0] = "abc";
sort[1] = "bcs";
sort[2] = "saa";
string s = sort[2];
string s2 = sort[0];
索引器可以重载,如果重载,需要有不同的参数列表。
分部类
分部类使用partial修饰符,分部类可以让一个类分在几个文件中完成,在socket网络游戏编程这部书中,处理协议的函数就是写在一个类的许多分部类中。分部方法
分部方法是在分部类中,分部方法把一个方法分割为一个方法的声明,和一个方法的实现。它有以下几个要求:
1、返回类型必须是void。
2、签名不能包括访问修饰符,也就是说分部方法是分部类的隐式私有的。
3、参数列表不能包含out参数。
4、声明个实现部分都是用partial上下文关键字,放在void前面。
——继承
可以使用父类引用,子类实例,因为子类包含父类需要的一切,在子类实例化时,有一部分是基类,所以基类可以去引用;但是基类实例化是没有派生类的,所以不可以反过来。
new和virtual、override的区别
new和virtual、override容易让人混淆头晕
首先new关键字用于派生类不希望使用基类的成员(函数成员字段成员都可以使用,不能对static使用)时,可以做到屏蔽的作用,不会干扰到基类的成员。比如:
class Base
{
public string str = "base";
public void Print()
{
Console.WriteLine(str);
}
}
class Child : Base
{
new public string str = "child";
new public void Print()
{
str += " this";
Console.WriteLine(str);
}
}
class Program
{
static void Main(string[] args)
{
Base bas = new Base();
Child child = new Child();
Base bas1 = new Child();
bas.Print(); //打印base
child.Print(); //打印child this
bas.Print(); //打印base
Console.ReadLine();
}
}
而virtual、override只能作用于函数成员,如方法,属性等,不能重写static类型,虽然也能做到派生类屏蔽基类成员的作用,这与new关键字效果相同。但是更重要的是,在父类引用,派生类实例时,创建的对象会向上找,找到最高的那个重写(忽视低的)然后调用。
class Base
{
public string str = "base";
virtual public void Print()
{
Console.WriteLine(str);
}
}
class Child : Base
{
override public void Print()
{
string str = "child";
Console.WriteLine(str);
}
}
class Second : Child
{
public override void Print()
{
string str = "second";
Console.WriteLine(str);
}
}
class Program
{
static void Main(string[] args)
{
Base bas = new Base();
Child child = new Child();
Second second = new Second();
Base bas1 = new Child();
Base bas2 = new Second();
Child child1 = new Second();
bas.Print(); //打印base
child.Print(); //打印child
second.Print(); //打印second
bas1.Print(); //打印child
bas2.Print(); //打印second
child1.Print(); //打印second
Console.ReadLine();
}
}
构造函数的执行
在继承链中,每个类执行自己的构造函数体之前都会执行其基类的构造函数。因此,不要在基类构造函数中调用虚函数,因为基类构造函数执行时,调用虚函数,而派生类还没有完全初始化。派生类使用基类构造函数有两种形式,第一种是使用base,第二种是使用this。一般都是用base,this更好的用法是用在一个类拥有多个构造函数时,把多个构造函数相同的部分提取出来,然后其他构造函数通过this使用这个提取出来的构造函数,如下:
class Base
{
public string str = "base";
public Base()
{
str = "new base";
}
public Base(string str) : this()//通过this使用其他的构造函数
{
Console.WriteLine(str + this.str);
}
}
class Program
{
static void Main(string[] args)
{
Base bas = new Base("this ");//打印this new base
Console.ReadLine();
}
}
抽象类和抽象函数成员
使用abstract关键字修饰。
抽象类有以下要求:
1、不能被实例化。
2、主要用途用于被继承,并且抽象类可以继承其他抽象类。
3、抽象类既可以有抽象函数成员,又可以有普通函数成员。
抽象函数成员:
1、只能有签名,不能有函数体。
2、只能设置函数成员(方法,属性,事件,索引器),不能设置字段成员。
3、继承该抽象类,必须重写所有的抽象函数成员。
密封类
使用sealed关键字修饰,表示这个类不允许类继承。
静态类
静态类就是用static修饰的类,主要用途就是作为工具类,具有以下特点:
1、所有成员必须全部都是静态的,不允许普通成员。
2、静态类不允许被继承,也就是隐式密封类。
扩展方法
这是一个十分实用的功能
它的作用是让你可以向第三方的静态类中添加我们自己定义的函数,然后依然通过第三方静态类调用。它有几个条件:
1、扩展方法必须卸载静态类中。
2、扩展方法必须包含关键字this的参数作为第一个参数,并在后面跟上要扩展的类的类的名称和引用。