.NET基础回顾(二)
一.结构
- 结构是一个值类型。
- 使用struct关键字来定义一个结构,级别与类保持一致,写在命名空间下面。
- 结构中可以定义字段,属性,方法,构造函数,也可以通过new关键字来创建对象。
- 结构中的字段不能赋初始值。
- 无参数的构造函数无论如何C#编译器都会生成,所以我们不能为结构体定义一个无参构造函数。
- 再构造函数中必须为结构体的所有字段进行赋值。
- 再构造函数中为属性赋值,不认为是对字段赋值,因为属性不一定是去操作字段。
- 不能定义自动属性,因为自动属性会生成一个字段,而这个字段必须要求在构造函数中,但是我们又不知道这个字段叫什么名字。
- 当我们要表示一个轻量级的对象的时候,就可以定义结构,以提高速度。根据传值的影响来选择,希望传引用就定义为类,希望穿拷贝就定义为结构。
二.垃圾回收机制
- 托管代码和非托管代码。被CLR管理的代码是托管代码,分配在栈空间的变量,一旦执行完其所在的作用域,这个变量就会被CLR立即回收。
- 值类型变量的定义都是结构,分配再栈空间,引用类型变量的定义都是类,分配在堆空间。
- 分配在堆里面的对象,当没有任何变量引用他的时候,这个对象就被标记为“垃圾对象”,等待垃圾回收器回收(Garbage Collection),GC会定时清理堆空间中的垃圾对象。
- GC清理垃圾的频率程序员无法决定,CLR会根据电脑配置,代码性能自动控制。
- GC代码调用(“代”的概念):
GC.GetGeneration(p);得到指定对象所在的代;
GC.MaxGeneration;返回代数;
GC.Collection();立即让垃圾回收器对所有的代进行回收;
GC.Collection(int);对指定的代立即进行垃圾回收;
三.析构函数
示例:
~Person()
{
Console.WriteLine(“我是析构函数!”);
}
- 不能有访问修饰符,不能有参数;
- 在对象被垃圾回收器回收的时候,析构函数被GC自动调用;
- 执行一些清理善后的操作的时候,会用到析构函数。
四.静态成员
- 静态成员是被static关键字修饰的,是属于类的,通过类名.静态成员来访问。
实例成员是没有static关键字修饰的,是属于对象的,通过对象名.实例成员来访问。
2.在一个类被加载的时候,这个类下的所有静态成员都会被加载。
3.静态成员只被创建一次,所以静态成员在整个程序的运行中只有一份,而对于示例成员来说,有多少对象就有多少份。
4.静态成员会被创建在静态存储区中,一旦创建,直到程序退出才会被回收。静态成员一定程度上会对程序的效率产生影响。
5.变量需要被共享,在整个程序中需要经常被调用的时候,就可以将这些成员定义为静态成员。
6.在静态方法中,不能直接调用实例成员,因为静态方法被调用的时候,对象还有可能不存在。
7.this/base关键字在静态方法中不能使用,因为有可能对象还不存在。
8.在实例方法中可以调用静态成员,因为这个时候,静态成员肯定存在。
静态成员和实例成员的比较:
(1)生命周期;
(2)存储位置;
五.静态类
- 被static关键字修饰的类。
- 静态类中只能声明静态成员。
- 静态类中不能有实例构造函数。
- 静态类不能被实例化,因为没有实例成员,实例化没有意义。
- 静态类也不能被继承。
- 静态类的本质是抽象的密封类。
- 如果一个类下面的所有成员都需要被共享,就把这个类定义为静态类。
- 不能声明一个静态类型的变量。
六.静态构造函数
- 非静态的类都可以有静态构造函数
- 一个类的成员第一次被访问的时候就会执行静态构造函数,只被执行一次,无论以后再次调用,都不会执行静态构造函数了。
程序示例:
1 public class Person 2 { 3 static public int num; 4 public Person() 5 { 6 num=1; 7 Console.WriteLine("实例构造函数"); 8 } 9 static Person() 10 { 11 num=2; 12 Console.WriteLine("静态构造函数"); 13 } 14 } 15 static void Main(string[] args) 16 { 17 Console.WriteLine(Person.num); //输出:2 18 Person p = new Person(); 19 Console.WriteLine(Person.num); //输出:1 20 Console.ReadKey(); 21 }
七.继承
- 创建子类对象的时候,再子类对象中会为子类对象的字段开辟空间,也会为父类对象的所有字段开辟空间。
- 子类从父类继承父类所有的非私有成员。
- base关键字可以调用父类的非私有成员,通过:base()可以调用父类的无参构造函数。
- 子类的访问级别不能高于父类。
- 创建子类对象的时候会调用父类的构造函数,如果父类没有无参构造函数,子类会报错,因为子类对象会默认调用父类的无参构造函数。
- 通过:base()可以显示地调用父类的有参构造函数。
程序示例:
1 public Student():base(12,”jack”,true) 2 { 3 Console.WriteLine(“我是子类构造函数……”); 4 }
7. 在调用子类的时候,为防止数据冲突,会优先处理父类中的数据,完成父类数据的初始化。
8.继承的特征:
(1) 单根性,子类只能有一个父类;
(2) 传递性;
9.Object是所有类的祖宗类,所有的类都是从object类继承的。
10.什么情况下会用到继承?
父类只要有一个功能不是子类所需要的,子类就不应该继承,子类和父类是is a的关系。例如,狗会走,人也会走,但是Person类不能继承Dog类;然而Student类可以继承Person类。
11.子类成员与父类成员存在同名的时候?
父类与子类存在同名的时候,如果创建一个子类对象,调用这个子类对象的同名方法,会调用子类的。
12.new关键字的第二个作用,隐藏父类的同名成员。
程序示例:
父类:
1 class Person 2 { 3 Public void Test() 4 { 5 Console.WriteLine(“我是父类的”); 6 } 7 }
子类:
1 class Student:Person 2 { 3 public new void Test() 4 { 5 Console.WriteLine(“我是子类的”); 6 } 7 }