【C#】第3章学习要点(二)自定义类和结构
分类:C#、VS2015
创建日期:2016-06-19
使用教材:(十二五国家级规划教材)《C#程序设计及应用教程》(第3版)
一、要点概述
别人提供的类都是为了简化你的工作量用的,可是实际处理的事情千差万别,要通过写代码做实际的事,你还得自己定义类。因此,先把如何自定义类及其涉及的相关概念和要点掌握住,是写程序绕不过去的第一关。
二、类和成员的基本概念
1、基本格式
[访问修饰符] [static] class 类名 [: 基类 [,接口序列]]
{
[类成员]
}
要点:
(1)基类最多只能有一个。如果不定义基类,默认继承自System类。
(2)类成员包括字段、属性、构造函数、方法、事件、运算符、索引器、析构函数等。
(3)绝大多数情况下都不需要定义析构函数。只有在自己定义需要回收的资源而不是靠垃圾回收来自动对其进行清理时才需要定义析构函数。
示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Person { private static int n = 1; public string Name { get; set; } = string.Empty; public int Age { get; set; } = 0; public Person() { Console.WriteLine($"第{n++}次调用"); } } class Program { static void Main(string[] args) { Person p1 = new Person() { Name = "张三", Age = 20 }; Console.WriteLine($"姓名:{p1.Name},年龄:{p1.Age}"); Person p2 = new Person() { Name = "李四", Age = 22 }; Console.WriteLine($"姓名:{p2.Name},年龄:{p2.Age}"); Console.ReadLine(); } } }
2、访问修饰符
(1)基本访问修饰符
public:类的内部和外部代码都可以访问。
private:类的内部可访问,类的外部无法访问。如果省略类成员的访问修饰符,默认为private。
internal:同一个程序集中的代码都可以访问,程序集外的其他代码无法访问。如果省略类的访问修饰符,默认为internal。
protected:类的内部或者从该类继承的子类可以访问。
protected internal:从该类继承的子类或者从另一个程序集中继承的类都可以访问。
(2)特殊访问修饰符
当将同一个类用多个不同的文件来分别描述时,还可以在基本访问修饰符的后面同时加上partial修饰符。比如多人同时写同一个类时就可以这样用。
编译器编译源程序时,会自动将其合并到同一个类中。
3、构造函数
要点:
(1)构造函数是创建对象时自动调用的函数。一般在构造函数中做一些初始化工作,或者做一些仅需执行一次的特定操作。
(2)构造函数没有返回类型,并且它的名称与其所属的类的名称相同。
(3)构造函数可重载。
(4)在扩充类的构造函数中调用基类提供的方法时,用“base.方法名”实现。
4、静态类和静态方法
要点:
(1)可以在方法名的前面加上static表明这是一个静态方法。
(2)可以在class的前面加上static表明所定义的类是一个静态类。在这种情况下,该类中的所有成员都必须是静态的(都必须带有static修饰符)。
(3)在C#语言中,通过“类名.方法名”来调用静态方法,通过“实例名.方法名”来调用实例方法。
(4)静态方法可以被重载但不能被重写。
注意:
(1)声明为static的成员在内存中只有一份。
(2)首次调用时加载到内存,所有成员都不再调用时从内存中移除,这些工作都是由垃圾回收器自动完成的。
5、属性
要点:
(1)属性(property)是字段的扩展,用于提供对字段读写的手段。
(2)属性和字段的区别是属性不表示存储位置,而是通过get访问器和set访问器指定读写字段的值时需要执行的语句。根据使用情况不同,可以只提供get访问器或者只提供set访问器,也可以两者同时提供。
(3)基本用法示例:
public string Name { get; set; } = string.Empty;
public int Age { get; set; } = 0;
public int Grade { get; private set; }
6、方法
要点:
(1)定义方法时,在参数名的前面可以使用的关键字有:
ref、out、params
(2)如果定义方法时不在参数名的前面添加关键字,一定要注意默认情况下值类型和引用类型的调用区别。
(3)方法重载
指具有相同的方法名,但“参数类型”或“参数个数”不完全相同的多个方法可以同时出现在同一个类中。在项目开发过程中,很多方法都需要使用方法重载来实现。
7、事件
事件是靠委托来实现的。由于项目中会大量使用委托和事件完成各种功能,因此后面用单独的一章介绍它。
8、类的封装、继承和多态性
属于高级用法,与编程经验关系很大,是初学者的难点但也是项目中最能体现核心技术的优势和差别的地方。
(1)封装
抽象类:用abstract关键字声明。抽象就是把公用的东西抽取出来放到一个单独的类中,这样既可以要求扩充类必须实现某些在抽象类中仅有声明没有实现的方法,也可以在抽象类中直接实现某些大家公用的方法。
密封类:用sealed关键字声明。在类的定义中使用该关键字表明该类不能被继承,在方法的定义中使用该关键字表明该方法不能被重写。
(2)继承
继承的目的是为了避免重复写相同的代码。如果用不太严谨的说法来描述它,可将其理解为对要处理的事情分层管理。
要注意继承中构造函数的处理。
(3)多态
注意下列关键字的用法:
virtual、override:基类的方法定义中用virtual表示该方法可以被扩充类重写,扩充类中用override表示该方法重写的是基类中同名的方法。
new:基类的方法定义中没有用virtual声明(即:不允许被重写),但是你仍然需要重写它,此时可以用这个关键字。
三、自定义结构
要点:
(1)自定义结构时,用struct关键字。从定义形式上看,它和类的区别仅有一个单词不一样(结构用struct关键字声明,而类用class关键字声明),其他都一样。
(2)结构不能被继承。
(3)结构和类的区别在于执行时的性能:结构的变量值都是在栈中保存的(速度快),而类的变量值都是在堆中保存的(慢一点)。
(4)凡是自定义的结构,都可以用自定义的类来实现。如果搞不清用结构好还是用类好,那就暂不考虑性能,全部都用类来实现就行了。随着开发经验的增加,你以后自然会理解哪些情况下应该用结构来实现。