1、C语言经典入门教程,C# 的基本数据类型,static void Main(string args) / 声明一个值类型的整型数据类型int value = 130;Console.WriteLine(“该变量的初始值为 0“, value); Test(value);/ 由于该数据类型属于值类型,所以将恢复其初始值 Console.WriteLine(“该变量的值此时为 0“, value); static void Test(int byVal) int t = 20;byVal = t* 30; ,将value的初始值传递给Test()方法,不反映已经改变的val值,而保留原始值,C#
2、的基本数据类型,static void Main(string args) DataType objTest = new DataType ();objTest.Value = 130;/ 传递属于引用类型的对象Test(objTest);/ 由于该数据类型属于引用类型,所以会考虑新处理的值 Console.WriteLine(“变量的值为 0“, objTest.Value); static void Test(DataType data) int t = 20;data.Val = temp * 30; ,将 DataTypeTest 的引用传递给 Test(),被传递的value在Tes
3、t()中改变,反映已经改变的value值,class DataType public int Value; ,引用类型和值类型,System.Object方法,引用类型和值类型的内存分配,值类型存储在运行栈,引用类型存储在托管堆 Apparel myApparel = new Apparel(); Apparel myApparel1 = myApparel;,Class Apparel public double Price = 250.0;public string FabType = “Syn”; ,栈,托管堆,装箱与拆箱,装箱即将值类型转换为引用 int age = 17; Objec
4、t refAge = age 拆箱即将引用类型转换为值类型。 int newAge = (int)refAge; double newAge = (double)refAge; /错误,要具有相同类型,运算符和表达式,运算符和表达式,运算符和表达式,运算符和表达式,运算符和表达式 9-6,赋值运算符 (=),变量 = 表达式;例如:身高 = 177.5; 体重 = 78; 性别 = “m”;,运算符和表达式 9-7,一元运算符 (+/-),Variable +; 相当于Variable = Variable + 1;Variable -;相当于Variable = Variable - 1;,
5、运算符和表达式,运算符和表达式,C# 运算符的优先级,选择结构,语法:if ()else ,选择结构用于根据表达式的值执行语句,if else,条件:只能是bool类型的值,选择结构,switch (“cotton”) case “COTTON”: case “cotton”: break;case 值3: case 值4:break; ,switchcase,表达式可以是int、字符或字符串 C#不允许从一个case块继续执行到下一个case块。每个case块必须以一个跳转控制语句break、goto或return结束 多个case标签可以对应一个代码块,循环结构,循环结构用于对一组命令执行
6、一定的次数或反复执行一组命令,直到指定的条件为真。 循环结构的类型 while 循环 do 循环 for 循环 foreach 循环,条件:只能是bool类型的值,while 循环反复执行指定的语句,直到指定的条件为真 语法 : while (条件) / 语句 break 语句可用于退出循环 continue 语句可用于跳过当前循环并开始下一循环,while 循环,dowhile 循环,dowhile 循环与 while 循环类似,二者区别在于 dowhile 循环中即使条件为假时也至少执行一次该循环体中的语句。 语法 :do / 语句 while (条件),for 循环,for 循环要求只有
7、在对特定条件进行判断后才允许执行循环 这种循环用于将某个语句或语句块重复执行预定次数的情形 语法 : for (初始值; 条件; 增/减) /语句 ,foreach 循环 2-1,foreach 循环用于遍历整个集合或数组 语法:foreach (数据类型 元素(变量) in 集合或者数组)/语句,foreach 循环2-2,static void Main(string args) / 存放字母的个数 int Letters = 0;/ 存放数字的个数int Digits = 0;/ 存放标点符号的个数int Punctuations = 0;/ 用户提供的输入 string instr;C
8、onsole.WriteLine(“请输入一个字符串 “);instr = Console.ReadLine();/ 声明 foreach 循环以遍历输入的字符串中的每个字符。 foreach(char ch in instr)/ 检查字母if(char.IsLetter(ch)Letters+;/ 检查数字if(char.IsDigit(ch)Digits+;/ 检查标点符号if(char.IsPunctuation(ch)Punctuations+;Console.WriteLine(“字母个数为: 0“, Letters);Console.WriteLine(“数字个数为: 0“, Di
9、gits);Console.WriteLine(“标点符号个数为: 0“, Punctuations); ,为所有计数器设置初始值,接受输入,对输入的每一个 字符都进行循环,使用了所有输入的字符 之后,循环自动终止,using System; public class WriteTest public static void Main()int array = 1, 2, 3, 4, 5 ;foreach (int item in array)Console.WriteLine(item); ,using System; public class WriteTest public static
10、 void Main()int array = 1, 2, 3, 4, 5 ;foreach (int item in array)item += item;Console.WriteLine(item); ,C#的预处理指令2-1,预处理指令是C#编译器在词法分析阶段读取的语句。这些语句可以指示编译器包含或不包含某些代码,甚至可以根据预处理指令的值终止编译。 预处理指令由字符#标识,并且字符#必须是该行的第一个非空字符。 预处理指令最常见的三个用途是:完成条件编译、增加诊断来报告错误和警告、定义代码域。,C#的预处理指令2-2,#define CLIENT #define DEBUG usi
11、ng System; public class MyApp public static void Main() #if DEBUG & INHOUSE #warning Debug in on. #elif DEBUG & CLIENT #error Debug not allowed in Client Code. #endif ,控制台输入和输出,数据输入(Read,ReadLine) Console.Read ()方法 Console.Read方法用来从控制台读取一个字符,其定义如下:Public static int Read(); Read方法返回所读取的字符的Unicode编码值。
12、 注意: Read方法的返回变量是32位的整数,如果需要得到输入的字符,则必须通过数据类型的显式转换才能得到相应的字符。,控制台输入和输出,Console.Read () /ReadTest.cs using System; public class ReadTest public static void Main()int i;char ch;i=Console.Read();ch=(char) i; /显式类型转换Console.WriteLine(i);Console.WriteLine(ch); ,运行结果: A 65 A,控制台输入和输出,Console.ReadLine ()方法
13、Console.ReadLine方法用来从控制台读取一行字符,定义如下:Public static string ReadLine(); Read方法返回所读取一行字符的字符串。一般情况下,一行输入是指从输入一个字符开始,遇到回车符号为止。,控制台输入和输出,/ReadLine.cs using System; using System.Globalization; public class ReadTest public static void Main()int i;double d;string str;str=Console.ReadLine(); /由控制台输入整数字符串i=int.
14、Parse(str); /整数字符串转换为整数Console.WriteLine(i);str=Console.ReadLine(); /由控制台输入浮点字符串d=double.Parse(str); /浮点字符串转换为浮点数Console.WriteLine(d); ,运行结果: 1234 1234 123.456 123.456,控制台输入和输出,数据输出(Write WriteLine) Console.Write ()方法 Console.Write方法用来向控制台输出一个字符,但控制台的光标不会移到下一行。其定义如下:public static void Write(XXX valu
15、e);public static void Write(string format,object o1,); 注意:格式化format同格式化函数Format中的格式化串类似,其格式如下:N,M:formatstring 其中,字符N表示输出变量的序号,M表示输入变量在控制台中所占的字符空间,如果这个数字为负数,则按照左对齐的方式输出,若为正数,则按照右对齐方式输出。,控制台输入和输出,/WriteTest.cs using System; public class WriteTest public static void Main()int i=32767;double d=456.5678
16、9;/由控制台。按照十进制输出整数及浮点数Console.Write(“i=0x0,8:Xtd=1,10:F3”,i,d);/由控制台。按照十六进制输出整数Console.Write(“i=0x0,-8:Xtd=1,-10:F3”,i,d); 输出结果:i=0x 7FFF d= 456.568i=0x7FFF d=456.568,控制台输入和输出,Console.WriteLine()方法 Console.WriteLine方法用来向控制台输出一行字符,即WriteLine方法在输出信息之后,在信息的尾部自动添加“rn”字符,表示回车换行。public static void WriteLin
17、e(XXX value);public static void WriteLine(string format,object o1,); 注意:格式化format同WriteLine中的格式化参数完全一样。,控制台输入和输出,/WriteLine.cs using System; public class WriteTest public static void Main()int i=32767;double d=456.56789;/格式化输出Console.WriteLine(“i=0x0,8:Xtd=1,10:F3”,i,d);Console.WriteLine(“i=0x0,-8:X
18、td=1,-10:F3”,i,d);Console.WriteLine(“i=0x0,-8:Dtd=1,-10:C3”,i,d); 输出结果: i=0x 7FFF d= 456.568 i=0x7FFF d=456.568 i=32767 d=¥456.568,第3章 C#面向对象设计,结构程序设计的不足数据与方法分离,void SpeedUp(int ,double speed = 0;,结构程序设计的不足代码不能重用,void main() int doorN_car1 = 2;int color_car1 = 0;int speed_car1 = 100;printf(“%d %d %d
19、n“, doorN_car1, color_car1, speed_car1);int doorN_car2 = 4;int color_car2 = 1;int speed_car2 = 80;printf(“%d %d %dn“, doorN_car2, color_car2, speed_car2); ,C#的面向对象特性,所有东西都是对象:变量和方法的集合。 初级特性:OO最基本的概念,即类和对象。 中级特性:OO最核心的概念,即封装、继承和多态。 高级特性:由初级特性和中级特性引出的一些问题,如构造函数的使用、覆盖的规则、静态变量和函数等。,初级特性,面向对象技术最基本的概念是类和对
20、象: 类是一个样板,以操作、表示和算法的形式完整地定义了一组对象的行为。它通常也是面向对象语言中的模块化、封装和数据抽象的基础。 对象是类的一个实例,是一个软件单元,它由一组结构化的数据和在其上的一组操作构成。,抽象数据类型,类实际上为实际的物体在计算机中定义了一种抽象数据类型。 抽象数据类型是仅由数据类型和可能在这个数据类型上进行的操作定义的。 使用者只能通过操作方法来访问其属性,不用知道这个数据类型内部各种操作是如何实现的。,class Car public int doorN;public int color;public int speed;public void SpeedUp()s
21、peed += 10; class MyApp static void Main()Car car1;car1.doorN = 2; car1.color = 0; car1.speed = 100;Car car2;car2.doorN = 4; car2.color = 1; car2.speed = 80; ,public double speed;,面向对象程序设计封装、代码重用,3.2 类与对象,类:C#所有的代码都是在某一个类中,因此不可能在类之外的全局区域有变量和方法。 对象:C#中的对象相当于一块内存区域,保存对象特有的类中所定义的数据。 引用:C#中对于对象的操作全部通过引用
22、进行。,3.2.1 类的定义 类使用class关键字声明。采用的形式为:类修饰符 class 类名称:基类以及实现的接口列表 类体 ;,类、对象和引用的声明,声明一个类:访问修饰字 class 类名变量声明,方法声明 class Student long id; / 学号char gender; /性别int classID; / 班级号,注意不能用class作属性名void ChangeClass(int aClassID) /更改班级 声明一个对象引用:类名引用名Student student; 创建一个对象:new 类构造函数 student = new Student(); /如果缺少
23、这一步编译器会报错 使用对象:引用名. 变量名/方法名(参数) student.id = 200328013203194;,引用与对象举例,引用类似于C+中的对象指针。但又有区别: 在C#中”引用“是指向一个对象在内存中的位置,在本质上是一种带有很强的完整性和安全性的限制的指针。 当声明某个类、接口或数组类型的一个变量时,变量的值总是某个对象的引用或者是null引用。 指针就是简单的地址而已,而引用除了表示地址而外,还是被引用的数据对象的缩影,可以提供其他信息。 指针可以有+、-运算,引用不可以运算。,3.1.2 类的成员 1类的成员分类 常量:表示与该类相关联的常量值。 字段:即该类的变量。
24、 类型:用于表示一些类型,它们是该类的局部类型。 方法:用于实现可由该类执行的计算和操作。 属性:用于定义一些命名特性,通过它来读取和写入相关的特性。 事件:用于定义可由该类生成的通知。 索引器:使该类的实例可按与数组相同的(语法)方式进行索引。 运算符:用于定义表达式运算符,通过它对该类的实例进行运算。 实例构造函数:用于规定在初始化该类的实例时需要做些什么。 析构函数:用于规定在永久地放弃该类的一个实例之前需要做些什么。 静态构造函数:用于规定在初始化该类自身时需要做些什么。,public class Furniture const double salesTax = .065;priva
25、te double purchPrice;private string vendor, inventoryID;public Furniture(string vendor, string inventID, double purchPrice)this.vendor = vendor;this.inventoryID = inventID;this.purchPrice = purchPrice;public string MyVendor get return vendor; public double CalcSalesTax(double salePrice) return saleP
26、rice * salesTax; ,字段,构造函数,成员属性,方法,2类成员的可访问性,类或结构的默认访问类型是internal。 类中所有的成员,默认均为private。,class Furniture const double salesTax = .065;private double purchPrice;private string vendor, inventoryID;public Furniture(string vendor, string inventID, double purchPrice)this.vendor = vendor;this.inventoryID =
27、inventID;this.purchPrice = purchPrice;public string MyVendor get return vendor; public double CalcSalesTax(double salePrice) return salePrice * salesTax; ,class MyApp static void Main()Furniture f = new Furniture(“aaa“, “001“, 1.2);Console.WriteLine(f.salesTax);Console.WriteLine(Furniture.salesTax);
28、f.purchPrice = 10;string str = f.MyVendor; ,错误,3.1.3 构造函数,构造函数是一种用于对象初始化的特殊方法,有以下特点。构造函数只能在对象创建时调用,即和new运算符一起被调用。构造函数和类具有相同的名字。构造函数可以有0个、1个或多个参数。构造函数没有返回值。每个类至少有一个构造函数,一个类可以有多个构造函数。如果没有为类定义构造函数,系统会自动为其定义一个缺省的构造函数。缺省构造函数不带参数,作用是将实例变量都清零。一旦为类定义了构造函数,则系统不会再为其定义缺省构造函数。 C#中构造函数有三种:实例构造,私有构造和静态构造,创建对象与构造函
29、数 类声明后,可以创建类的实例,即对象。创建类的实例需要使用new关键字。类的实例相当于一个变量,创建类实例的格式如下: 类名 对象名=new 构造函数(参数类表); 例如: Point myPoint = new Point();,类的构造函数可通过初始值设定项来调用基类的构造函数,例如: public Student(string no, string name,char sex,int age) : base(name, sex,age) 类的构造函数也可通过关键字this调用同一个类的另一个构造函数,例如: public Point() : this(0,20) ,构造函数举例,cla
30、ss Student long id;char gender;int classID;public Student() : this(0, F, 0) public Student(long aID, char aGender, int aClassID)id = aID;gender = aGender;classID = aClassID; ,私有构造函数,在某些特殊的情况下,使用私有构造函数能够达到意想不到的效果。比如,想建立这样一个类:不允许被其他类实例化,但提供对外的静态接口成员。在.NET框架类库中就存在这样的类,如System.Math类就不能够实例化,它的所有成员都是静态的。
31、用关键字private修饰的构造函数就是私有构造函数。,下面的代码建立一个无法实例化的类filling: public class filling private filling() /私有构造public static void happy()Console.WriteLine (“How happy!“);public static void sad()Console.WriteLine (“So sad!“); public class MainClass public static void Main()/filling f1=new filling(); /不能实例化filling.
32、happy();filling.sad(); ,析构函数,C#支持析构函数。虽然C#能够自动进行垃圾回收,但对于某些资源,.Net不知道如何回收,所以需要人工的内存回收。 在.net 编程环境中,系统的资源分为托管资源和非托管资源。 托管资源,如简单的int,string,float,DateTime 等等,是不需要人工干预回收的。 非托管资源,例如文件,窗口或网络连接,对于这类资源虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理这些资源。在使用完之后,必须显式的释放他们,否则会占用系统的内存和资源,而且可能会出现意想不到的错误。 .net 中超过80%的资源都是托管
33、资源。,析构函数与Finalize,.NET Framework 提供Object.Finalize方法,默认情况下,Finalize 方法不执行任何操作。如果需要可以覆盖Finalize方法。 通过析构函数可以自动生成Finalize方法和对基类的Finalize方法的调用。public class Chair public Chair() .Chair() .void Finalize() 如果试图既编写析构函数又编写Finalize方法,将导致编译器出错。,非托管资源:Dispose方法,对象析构举例, Dispose 方法是编程人员需要立即释放资源时调用,所以在Dispose 方法中调
34、用Close,并通知GC在回收垃圾时不需要再释放资源。 析构函数是编程人员在没有调用Dispose方法释放资源的情况下由GC在回收垃圾时调用。 1一般不要提供析构函数,因为它不能及时地被执行; 2实现Dispose方法的时候,一定要加上“GC.SuppressFinalize( this )”语句。,using System; class MyFile public MyFile() /Open Filepublic void Close() /Close Filepublic void Dispose() Close(); GC.SuppressFinalize(this); MyFile(
35、) Close(); class MyApp public static void Main()MyFile file = new File();.file.Dispose(); ,问题: 用Student对象保存学生信息,希望每个对象有一个单独的编号。第一个创建的对象编号为0,第二个对象编号为1,以此类推。 这就需要有一个所有Student对象都能访问的变量counter,而且变量counter在所有实例中共享。当一个对象创建时,构造函数增加counter值,下一个对象创建时使用增加过的值。 解决方法: C#编程语言没有这样的全局变量,但类变量是可以从类的任何实例访问的单个变量。 类变量在某
36、种程度上与其它语言中的全局变量相似。但仅限于同类型的对象访问。,类中的静态问题,静态变量,类变量是在所有类的实例(对象)中共享的变量,在变量声明中用static关键字表示。 类变量可以被标记为public或private。如果被标记为public,不需要类的实例就可以访问。 public class Student private int serialNumber;private static int counter = 0;public Student() serialNumber = counter;counter+; ,class MyApp static void Main()Stud
37、ent stu = new Student();Console.WriteLine(stu.serialNumber);Student stu1 = new Student();Console.WriteLine(stu1.serialNumber); ,静态方法,类方法是不需要类的任何实例就可以被调用的方法,在方法声明中用static关键字表示。 类方法只能访问静态变量,访问非静态变量的尝试会引起编译错误。 静态方法不能被覆盖成非静态的。 main是静态的,因为它必须在任何实例化发生前被访问,以便应用程序的运行。 public class GeneralFunction public sta
38、tic int AddUp(int x, int y) /静态方法return x + y; public class UseGeneral public void method() int c = GeneralFunction.AddUp(9, 10); /调用静态方法System.Console.WriteLine(“addUp() gives “ + c);,静态构造函数,问题:在Student类的例子中,如果希望对象编号不是从1开始,而是从0到1000之间的随机的数开始。 构造函数中虽然可以执行代码,但每个对象创建时都执行,而本例中只希望第一个对象创建时执行。,解决:C#中支持静态构
39、造函数,静态构造函数在类中第一个对象初始化或引用任何静态成员之前执行。,using System;public class Student public int serialNumber;private static int counter;static Student()Random rand = new Random(0);counter = rand.Next(0, 1000);public Student() serialNumber = counter;counter+; class MyApp static void Main()Student stu = new Student(
40、);Console.WriteLine(stu.serialNumber);Student stu1 = new Student();Console.WriteLine(stu1.serialNumber); ,静态构造函数用于初始化类。在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类。 using System; class BaseClass private static int count;static BaseClass()count = 0;Console.WriteLine(“aaaa“);public BaseClass()Console.WriteLin
41、e(“bbbb“); class MyApp static void Main()BaseClass a = new BaseClass();BaseClass a1 = new BaseClass(); 静态构造函数既没有访问修饰符,也没有参数。 无法直接调用静态构造函数。 在程序中,用户无法控制何时执行静态构造函数。 静态构造函数的典型用途是:当类使用日志文件时,将使用这种构造函数向日志文件中写入项。,3.3 类成员,1.字段成员 字段只是类中声明的一个变量,用来在对象中存储信息。 (1).静态字段 使用static关键字修饰的就是静态字段,静态字段属于类而不属于某个类实例,对它的访问使用
42、“类名.静态字段名” ,不能使用“对象名.静态字段名”的格式。 静态字段通常用来保存当前类的实例个数,例3-2:编写一个类,使用静态字段计算类的实例数量。 public class theclass public theclass()count+; /计数器增1public void showcount()Console.WriteLine(“实例数为:” + count );private static int count=0; /显式赋初值 public class Test public static void Main()theclass class1=new theclass();c
43、lass1.showcount();theclass class2 =new theclass();class2.showcount(); ,运行结果: 实例数为:1 实例数为:2,(2).只读字段当字段声明中包括readonly修饰符时,该字段成为只读字段。只能在声明只读字段的同时赋初值。其他任何时候都不允许为只读字段赋值。 public class Class1 public readonly string str1=”I am str1”; 执行下面代码: Class1 c1=new Class1(); Console.WriteLine(c1.str1); /c1.str1=“Chan
44、ge readonlyfiled”;错误 如果在类定义中显式添加一个构造函数,可以在构造函数中改变只读字段的值。 Public class Class1 Public readonly string str1=”I am str1”;public Class1() str1=“initialized by constructor!”; ,2.方法成员 方法成员的本质就是在类中声明的函数,描述类能够“做什么”。 (1).方法声明格式 访问修饰符 返回类型 方法名称 (参数列表) 方法体; 省略访问修饰符时,默认为private,例如,下面给出一个矩形类的代码,其中声明了三个方法。 public
45、class myRect private System.Drawing.Point p0;private int a, b;public myRect(int aa,int bb, System.Drawing.Point p)a = aa; b = bb; p0 = p;public int Area() /求面积Return (a * b);public int round() /求周长Return (2 * (a + b);public void move(int dx, int dy) /移动顶点p0.X += dx;p0.Y += dy; ,using System.Drawing;
46、 public class myRect private Point p0;private int a, b;public myRect(int aa,int bb, Point p)a = aa; b = bb; p0 = p;public int Area() /求面积Return (a * b);public int round() /求周长Return (2 * (a + b);public void move(int dx, int dy) /移动顶点p0.X += dx;p0.Y += dy; ,(2).方法重载 重载规则: 方法名相同 方法的参数列表不同:参数个数、参数数据类型例
47、如3-3,下面建立一个类Operate,该类有两个重载方法,分别对整型和浮点型做加法运算。 public class Operate public long Add(long a, long b)return(a*b);public double Add(double a, double b)return(a+b); 当在程序中使用时,会根据实参数据类型自动选择调用。 Operate p = new Operate(); Console.WriteLine(p.Add(3,5); /返回15 Console.WriteLine(p.Add(1.03,3.25); /返回4.28,(3).静态方
48、法 使用static关键字来修饰。静态方法不需要类实例,直接使用“类名.方法名”格式调用。在静态方法体内不能够直接使用非静态成员,也没有this引用,因为没有实例可以引用。,例如3-4 : public class Operate public long Add(long a, long b)return(a+b);public double Add(double a, double b)return(a+b);public static void hi() /静态方法 Console.WriteLine(str); /可以访问静态成员/Add(3,5); /不能访问实例成员private static string str=“you use s static method“; 再main()方法中调用下面的语句:Operate.hi();,