知识点:了解.NET 特性、 掌握.NET 框架结构组成和原理、掌握类和对象的概念、 掌握封装的基本概念
参考复习资料:C#编程基础第一课:C#和.NET框架、VS软件基本使用、编写第一个C#程序
1、 .NET 平台概述
1.1 .NET 平台的魅力
- 开发语言完全支持面向对象,有强大的类库支持。
- 强大的 Web 应用开发支持,我们能使用 ASP.NET 等技术开发各种网站应用。如 Dell 公司的网站和国外非常流行的社交网站 MySpace 就是用 ASP.NET 开发的。
- 强大的 Web Service 支持,Web Wervice 是构建互联网应用重要的技术,使用它可以轻松实现 各种应用程序间的网络通信。携程网站的后台订票系统就是 WebService 开发的。
- 支持 SOA 和云计算,.NET 支持 SOA(Service-Oriented Architecture)面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。同时支持云计算, Windows Azure 就是微软退出的云计算开发平台。
- WPF技术,WPF是微软新一代图形系统,运行在.NET Framework 3.0及以上版本,为用户界面、 2D/3D 图形、文档和媒体提供了统一的描述和操作方法。基于DirectX 9/10技术的WPF不仅带来了前所未有的3D界面,而且其图形向量渲染引擎也大大改进了传统的2D界面,比如Windows 中的半透明效果的窗体等都得益于WPF。程序员在WPF的帮助下,要开发出媲美Mac程序的酷炫界面已不再是遥不可及的奢望。
2、 .NET 框架结构
2.1 CLR
- CTS(Common Type System): 由于.NET 支持多种语言,每种语言的数据类型都是不一样的,通过通用类型系统可以解决数据类型不同的问题,如 C#中的 int 类型,在 VB 中是 Integer,CTS 把它们编译成 Int32,所有语言通用这种类型。
- CLS(Common Language Specification): 编程语言除了数据类型外,语法也有很大区别。CLS 公共语言规范就规范了不同语言所必须遵循的最低规范,以保证语言的互操作性。如 C#命名是区分大小写的,而 VB.NET 不区分,CLS 就规定编译后的中间代码命名除了大小写还需要有别的区别。
简单地说,CLR是CTS的实现,也就是说,CLR是应用程序的执行引擎和功能齐全的类库,该类库严格按照CTS规范实现。作为程序执行引擎,CLR负责安全地载入和运行用户程序代码,包括对不用对象的垃圾回收和安全检查。在CLR监控之下运行的代码,称为托管代码(managed code)。
2.2 FCL
3、 类和对象
- 将一组对象归纳为类,将对象的共性抽取出来形成类的过程叫:抽象化。
- 在类的概念模型下,将状态和行为具体化为实际对象的过程叫:实例化。
举例理解:类和对象的关系
比如,我们想购买20台电脑,在购买之前,会列出一个配置清单(CPU、内存、显示器……),到店以后和销售人员进行交流,确定配置清单。
- 那么配置清单就可以看做是一个类,对象:20台电脑
- 我们对类的更改,会影响到对象的更改,也就是通过类可以操作对象。比如,在配置清单(类)上,新增加一个或减少一个配件(属性、方法),那么会同时影响到20台电脑(对象)。
- 但是20台电脑是相互独立的,互不影响,比如说电脑可以安装不同的操作系统,也就是对象是相互独立的,对其中一个对象进行操作,不会影响同类下的另一个对象。
3.1 类
- 类是一种数据结构,可以包含数据成员(常量和字段)、函数成员(方法、属性、事件、索引器、运算符、实例构造函数、静态构造函数和析构函数)以及嵌套类型。
- C#中一切类型都为类,除(引用的命名空间外)所有的语句都必须位于类(或者结构)内,不存在任何处于类(或结构)之外的语句。因此,类是C#语言的核心和基本构成模块。比如,默认代码中包含一个Program类。
类定义的具体语法形式如下:
类的访问修饰符 类的修饰符 class 类名
{
//类的成员
}
- 类的访问修饰符:用于设定对类的访问限制,包括 public、internal 或者不写,用 internal 或者不写时代表只能在当前项目中访问类;public 则代表可以在任何项目中访问类。(类的成员在定义的时候没有显示的写出访问修饰符,则默认是private。对应到字段和属性中,通常字段修饰为private,属性修饰为public。)
- 类的修饰符:修饰符是对类本身特点的描述,包括 abstract、sealed 和 static。abstract 是抽象的意思,使用它修饰符的类不能被实例化;sealed 修饰的类是密封类,不能 被继承;static 修饰的类是静态类,不能被实例化。
- 类名:类名用于描述类的功能,因此在定义类名时最好是具有实际意义,这样方便用户理解类中描述的内容。在同一个命名空间下类名必须是唯一的。
- 类的成员:在类中能定义的元素,主要包括字段、属性、方法。
3.2 字段
字段又称为:“成员变量”,一般在类的内部做数据交互使用。 字段的命名规范:camel命名法(首单词的首字母小写,后面其他单词的首字母大写)。
通俗的理解字段:
- 私有化:字段就好比我们的个人财产,仅供个人使用,所以一般是private修饰。
- 添加标准:根据程序的功能需求,具体来添加需要的不同类型的字段。
注意:如果类型的定义中,没有指定字段的初始值,使用对象时也没有给字段赋值,那么字段将会被赋予其类型的默认值:
- 整数(包括字符和枚举)和实数类型的默认值为 0
- 布尔类型的默认值为 false
- 所有的引用类型的默认值为 null
测试:
namespace ConsoleApp1
{
class Student//声明一个类
{
private string _name;//声明一个字段
public string Name { get; set; }//声明属性
private string _gender;
public string Gender { get; set; }
private int _age;
public int Age { get; set; }
private bool _wuHan;
public bool WuHan { get; set; }
}
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student();//new一个对象
stu1.Name = "张三";//只给对象的Name属性赋值,其他属性没有赋值
Console.WriteLine("{0}你好,你的性别是:{1},你的年龄是:{2},是否武汉人:{3}",stu1.Name,stu1.Gender,stu1.Age,stu1.WuHan);
Console.ReadLine();
}
}
}
输出结果:
3.3 属性
- 属性的作用:在面向对象设计中主要使用属性描述对象的静态特征。
- 属性的命名规范:一般采用Pascal命名法(首字母大写),数据类型要和对应的字段要一致,一般属性名称也和字段一致,只是首字母大写。
属性的理解:
- 属性其实就是外界访问私有字段的入口,属性本身不保存任何数据,在对属性赋值和读取的时候其实就是操作的对应私有字段。
- 属性本质其实就是一个方法,通过get和set方法来操作对应的字段。
C#中定义属性的语法:
private string _name; //定义字段
public string Name //定义属性
{
get{return _name;}
set{_name = value;}
}
定义属性时,我们需要首先定义一个私有字段,再定义一个公开的属性封装该字段,属性中定义了 get 和 set 访问器,通过 get 访问器可以访问私有字段的值,通过 set 访问器可以设置该字段的值。 属性按读写类型分为三种:
- 读写属性:get、set 访问器都有
- 只读属性:只有 get 访问器
- 只写属性:只有 set 访问器
- 在 C#3.0 中,提供了新的特性:自动属性。如 Name 属性可以直接写成: public string Name{get;set;} 自动属性不需要定义私有字段(该字段由系统自动生成),简化了代码,用于定义没有逻辑判断的简单属性。
属性的作用:
- 避免出现非法数据,例如一个年龄属性,正常逻辑是年龄是不可以出现负数的,如果用户对年龄进行了负数的赋值,我们通过属性的set方法加入判断逻辑,从而排除这种非法数据。
private int _age;
public int Age
{
get { return _age; }
set
{
if (value < 0)
{
_age = 18;
}
else
{
_age = value;
}
}
}
- 限定属性只读或者只写,例如有些属性为了保护数据,我们只能读取,而不能赋值。具体使用的话,我们根据需要,屏蔽set或get方法达到只读和只写。
3.4 方法
方法是类的行为,C#中定义方法的语法是:
方法的访问修饰符 方法的返回值类型 方法名(参数列表)
{
//方法体
}
- 访问修饰符:决定了这个方法可以在哪里被调用。
- 修饰符:对这个方法进行一些特定的修饰。在定义方法时修饰符包括 virtual(虚拟的)、abstract(抽象的)、override(重写的)、static(静态的)、sealed(密封的)。override 是在类之间继承时使用的。
- 返回值类型:决定了方法执行完成之后,是否给调用的地方返回数据。返回数据可以是任意的数据类型(系统自带的类型,也可以是用户自定义的数据类型,即使用类作为返回类型,返回的是对象。),如果指定了返回值类型,必须使用 return 关键字返回一个与之类型匹配的值。如果没有指定返回值类型,必须使用 void 关键字表示没有返回值。
- 方法名:对方法所实现功能的描述。方法名的命名是以 Pascal 命名法为规范的(每个单词的首字母大写)。
- 参数列表:是在调用方法的时候,是否往方法里面传递数据。在方法中允许有 0 到多个参数,如果没有指定参数也要保留参数列表的小括号。参数的定义形式是“数据类型参数名”,如果使用多个参数,多个参数之间需要用逗号隔开。
补充说明:C#中return语句的使用方法
return语句用来终止它所在的方法的执行,并将控制权返回给调用方法,另外,它还可以返回一个可选值。如果方法为void类型,则可以省略return语句。
return语句后面可以是常量,变量,表达式,方法,也可以什么都不加。return语句可以出现在方法的任何位置。一个方法中也可以出现多个return,但只有一个会执行。当return语句后面什么都不加时,返回的类型为void。
示例练习1:声明一个类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Student
{
/*
* 类中可以存放的成员:
* 字段:采用_camelCase命名方式
* 属性:采用PascalCase命名方式
* 方法
*/
public string _name;//姓名
public string _gender;//性别
public int _age;//年龄
//字段和变量的区别:字段可以存放多个值,变量只能存放一个值
//声明一个方法,用以输出信息
//静态方法只能调用静态成员,非静态方法可以调用任何成员
public void Write()
{
Console.WriteLine("我叫{0},我是{1}生,我今年{2}岁了!",_name,_gender,_age);
}
}
}
第四步,实例化对象,并调用方法:在主程序Main方法中,实例化对象,并调用我们刚才写的方法。实现方法:在右侧解决方案资源管理器中,双击类名【Program.cs】,打开文件。
static void Main(string[] args)
{
//将类实例化,就是将类指定某个对象
Student zsStudent = new Student();
zsStudent._name = "张三";
zsStudent._gender = "男";
zsStudent._age = 19;
//调用非静态方法
zsStudent.Write();
Console.ReadLine();
}
第五步,预览效果:点击菜单栏【启动】,查看运行效果。
案例思考:再实例化一个对象,进行输出。同时声明一个变量,进行两次赋值,然后进行输出,观察结果对比。
static void Main(string[] args)
{
//将类实例化,就是将类指定某个对象
Student zsStudent = new Student();
zsStudent._name = "张三";
zsStudent._gender = "男";
zsStudent._age = 19;
string mystr = "王五";//声明一个变量,并赋值
//调用非静态方法
zsStudent.Write();
//实例化第二个对象
Student lsStudent = new Student();
lsStudent._name = "李四";
lsStudent._gender = "女";
lsStudent._age = 18;
mystr = "赵六";//给变量mystr,重新赋值
//调用非静态方法
lsStudent.Write();
Console.WriteLine(mystr);
Console.WriteLine(mystr);
Console.ReadLine();
}
示例练习2:属性的使用
第四步,声明方法:在Clerk类中,继续声明一个方法,用以输出自我介绍。
class Clerk
{
private string _name; //声明一个私有字段_name
public string Name { get; set; } //声明一个自动属性
private string _gender;
public string Gender //声明一个只读属性
{
get
{
_gender = "男";
return _gender;
}
}
private int _age;
public int Age //声明一个读写属性
{
get { return _age; }
set
{
if(_age<1 || _age > 100) //判断写入的年龄数据,是否符合逻辑
{
value = 18; //如果写入的年龄小于1或大于100,则设置value值为18
}
_age = value; //将value值,赋值给_age
}
}
//声明方法,输出职员信息
public void SayHello()
{
Console.WriteLine("我叫{0},我是{1}员工,我今年{2}岁!", Name,Gender,Age);
}
}
第五步,实例化对象,并调用方法:在主程序Main方法中,实例化对象,并调用我们刚才写的方法。实现方法:在右侧解决方案资源管理器中,双击类名【Program.cs】,打开文件。
static void Main(string[] args)
{
//实例化一个对象,语法:类名 对象名 = new 类名();
Clerk zsClerk = new Clerk();
//给对象相关属性赋值
zsClerk.Name = "张三";
//zsClerk.Gender = "女"; //Gender属性由于是只读属性,因此这里如果给它赋值会编译出错
zsClerk.Age = 0;
//调用方法,语法:对象名.方法名();
zsClerk.SayHello();
Console.ReadLine();
}
第六步,预览效果:在右侧【解决方案资源管理器】中,右键单击项目名称【ConsoleApp2】——点击【设为启动项目】,然后再点击菜单栏【启动】,查看运行效果。
- 属性的使用:保护字段,对字段的取值与赋值进行限定。属性往往被声明在字段的下方,并且将字段私有化。
- get属性访问器用于返回属性值,set属性访问器用于分配新值。
- 属性是逻辑字段,是字段的扩展,并不占用实际的内存;而字段占用内存空间。
- 属性可以被其他类访问;而非public的字段不能被直接访问。
- 属性可以对接受的数据在范围上做限定;而字段不能。
- 属性原则上是方法,内容保存在代码区。
3.5 封装
- 保证了数据的安全性
- 提供了外部访问的接口
- 类内部的修改不会影响其他类
3.6 类图
本课总结
- .NET 是一个面向网络、支持各种终端的开发平台。
- .NET 框架由 CLR(公共语言运行时)和 FCL(框架类库)组成。
- CLR 是.NET 应用程序的运行时环境,有两个主要组件:CLS(公共语言规范)和 CTS(通用类型系统)。
- FCL 提供了大量的类库帮助我们开发。
- 在.NET 平台上运行的语言会首先被编译成 MSIL(微软中间语言)。
- 属性是一种对字段的封装方式,包括:读写属性、只读属性、只写属性。