C# 学习笔记 4
来源:互联网 发布:手机九宫格软件 编辑:程序博客网 时间:2024/05/24 22:45
————————————————————————————–
C# 类(Class)
当你定义一个类时,你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据,但它定义了类的名称意味着什么,也就是说,类的对象由什么组成及在这个对象上可执行什么操作。对象是类的实例。构成类的方法和变量成为类的成员。
类的定义
类的定义是以关键字class开始,后跟类的名称,类的主体,包含在一对花括号内。下面是类定义的一般形式:
<access specifier> class class_name { // member variables <access specifier> <data type> variable1; <access specifier> <data type> variable2; ... <access specifier> <data type> variableN; // member methods <access specifier> <return type> method1(parameter_list) { // method body } <access specifier> <return type> method2(parameter_list) { // method body } ... <access specifier> <return type> methodN(parameter_list) { // method body }}
请注意:
访问标识符 指定了对类及其成员的访问规则。如果没有指定,则使用默认的访问标识符。类的默认访问标识符是 internal,成员的默认访问标识符是 private。
数据类型 指定了变量的类型,返回类型 指定了返回的方法返回的数据类型。
- 如果要访问类的成员,你要使用点(.)运算符。
点运算符链接了对象的名称和成员的名称。
下面的实例说明了目前为止所讨论的概念:
using System;namespace BoxApplication{ class Box { public double length; public double width; public double heigh; } class BoxExecute { static void Main(string[] args) { Box Box1 = new Box(); Box Box2 = new Box(); double volume = 0.0; Box1.length = 5.0; Box1.width = 6.0; Box1.heigh = 7.0; Box2.length = 10.0; Box2.width = 12.0; Box2.heigh = 13.0; volume = Box1.length * Box1.width * Box1.heigh; Console.WriteLine("Box1 的体积 {0}", volume); volume = Box2.length * Box2.width * Box2.heigh; Console.WriteLine("Box2 的体积 {0}", volume); Console.ReadLine(); } }}
成员函数和封装
类的成员函数是一个在类定义中有它的定义或原型的函数,就像其他变量一样。作为类的一个成员,它能在类的任何对象上操作,且能访问该对象的类的所有成员。
成员变量是对象的属性(从设计角度),且它们保持私有来实现封装。这些变量只能使用公共成员函数来访问。
让我们使用上面的概念来设置和获取一个类中不同的类成员的值:
using System;namespace BoxApplication{ class Box { private double length; private double width; private double heigh; public void setLength(double len) { length = len; } public void setWidth(double wid) { width = wid; } public void setHeigh(double hei) { heigh = hei; } public double getVolume() { return length * width * heigh; } } class BoxExecute { static void Main(string[] args) { Box Box1 = new Box(); Box Box2 = new Box(); double volume = 0.0; Box1.setLength(5.0); Box1.setWidth(6.0); Box1.setHeigh(7.0); Box2.setLength(10.0); Box2.setWidth(12.0); Box2.setHeigh(13.0); volume = Box1.getVolume(); Console.WriteLine("Box1 的体积 {0}", volume); volume = Box2.getVolume(); Console.WriteLine("Box2 的体积 {0}", volume); Console.ReadLine(); } }}
C# 中的构造函数
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
构造函数的名称与类的名称完全相同,它没有任何返回类型。
下面的实例说明了构造函数的概念:
using System;namespace LineApplication{ class Line { private double length; public Line() { Console.WriteLine("对象已经创建"); } public void setLength(double len) { length = len; } public double getLength() { return length; } } class LineExecute { static void Main(string[] args) { Line line = new Line(); line.setLength(11.0); Console.WriteLine("Length: {0}", line.getLength() ); Console.ReadLine(); } }}
默认的构造函数没有任何参数。但是如果你需要一个带有参数的构造函数可以有参数,这种构造函数叫做参数化构造函数。这种技术可以帮助你在创建对象的同时给对象赋初始值,具体请看下面实例:
using System;namespace LineApplication{ class Line { private double length; public Line(double len) { Console.WriteLine("对象已经创建"); length = len; } public void setLength(double len) { length = len; } public double getLength() { return length; } } class LineExecute { static void Main(string[] args) { Line line = new Line(10.0); Console.WriteLine("Length: {0}", line.getLength()); line.setLength(54.0); Console.WriteLine("Length: {0}", line.getLength()); Console.ReadLine(); } }}
C# 中的析构函数
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
下面的实例说明了析构函数的概念:
using System;namespace LineApplication{ class Line { private double length; public Line() { Console.WriteLine("对象已创建"); } ~Line() { Console.WriteLine("对象已删除"); } public void setLength(double len) { length = len; } public double getLength() { return length; } } class LineExecute { static void Main(string[] args) { Line line = new Line(); line.setLength(25.0); Console.WriteLine("Length: {0}", line.getLength()); Console.ReadLine(); } }}
C# 类的静态成员
我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本。
关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取。静态变量可在成员函数或类的定义外部进行初始化。你也可以在类的定义内部初始化静态变量。
下面的实例演示了静态变量的用法:
using System;namespace StaticVarApplication{ class StaticVar { public static int num; public void count() { num++; } public int getNum() { return num; } } class StaticTester { static void Main(string[] args) { StaticVar s1 = new StaticVar(); StaticVar s2 = new StaticVar(); s1.count(); s1.count(); s1.count(); s2.count(); s2.count(); s2.count(); Console.WriteLine("s1 的变量 num: {0}", s1.getNum()); Console.WriteLine("s2 的变量 num: {0}", s2.getNum()); Console.ReadKey(); } }}
你也可以把一个成员函数声明为 static。这样的函数只能访问静态变量。静态函数在对象被创建之前就已经存在。下面的实例演示了静态函数的用法:
using System;namespace StaticVarApplication{ class StaticVar { public static int num; public void count() { num++; } public static int getNum() { return num; } } class StaticTester { static void Main(string[] args) { StaticVar s = new StaticVar(); s.count(); s.count(); s.count(); Console.WriteLine("变量 num: {0}", StaticVar.getNum()); Console.ReadKey(); } }}
————————————————————————————–
C# 继承(Heritance)
继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。
当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。
继承的思想实现了 属于(IS-A) 关系。例如,哺乳动物 属于(IS-A) 动物,狗 属于(IS-A) 哺乳动物,因此狗 属于(IS-A) 动物。
基类和派生类
一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。
C# 中创建派生类的语法如下:
<acess-specifier> class <base_class>{ ...}class <derived_class> : <base_class>{ ...}
假设,有一个基类 Shape,它的派生类是 Rectangle:
using System;namespace InheritanceApplication{ class Shape { public void setWidth(int w) { width = w; } public void setHeigh(int h) { heigh = h; } protected int width; protected int heigh; } //派生类 class Rectangle: Shape { public int getArea() { return width * heigh; } } class RectangleTester { static void Main(string[] args) { Rectangle Rect = new Rectangle(); Rect.setWidth(3); Rect.setHeigh(4); Console.WriteLine("{0}", Rect.getArea()); Console.ReadLine(); } }}
基类的初始化
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。您可以在成员初始化列表中进行父类的初始化。
下面的程序演示了这点:
using System;namespace RectangleApplication{ class Rectangle { protected int length; protected int width; public Rectangle(int l, int w) { length = l; width = w; } public int getArea() { return length * width; } public void Display() { Console.WriteLine("length : {0}", length); Console.WriteLine("width : {0}", width); } } class Tabletop: Rectangle { //private int cost; public Tabletop(int l, int w): base(l, w) { } public int getCost() { return getArea() * 10; } public void Display() { base.Display(); Console.WriteLine("成本:{0}", getCost()); } } class RectangleExecute { static void Main(string[] args) { Tabletop t = new Tabletop(3, 4); t.Display(); Console.ReadLine(); } }}
C# 多重继承
多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。
C# 不支持多重继承。但是,您可以使用接口来实现多重继承。下面的程序演示了这点:
using System;namespace InheritanceApplication{ class Shape { public void setWidth(int w) { width = w; } public void setHeigh(int h) { heigh = h; } protected int width; protected int heigh; } public interface PaintCost { int getCost(int area); } class Rectangle: Shape, PaintCost { public int getArea() { return width * heigh; } public int getCost(int area) { return area * 10; } } class RectangleTester { static void Main(string[] args) { Rectangle rect = new Rectangle(); int area; rect.setWidth(3); rect.setHeigh(4); area = rect.getArea(); Console.WriteLine("面积:{0}", rect.getArea()); Console.WriteLine("成本:{0}", rect.getCost(area)); Console.ReadLine(); } }}
————————————————————————————–
C# 多态性(Polymorphism)
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为”一个接口,多个功能”。
多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:
- 函数重载
- 运算符重载
运算符重载将在下一章节讨论,接下来我们将讨论函数重载。
函数重载
您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
下面的实例演示了几个相同的函数 print(),用于打印不同的数据类型:
using System;namespace PolymorphiseApplication{ class Printdata { public void print(int i) { Console.WriteLine("Printing int: {0}", i); } public void print(double f) { Console.WriteLine("Printing float: {0}", f); } public void print(string s) { Console.WriteLine("Printing string: {0}", s); } } class PrintdataExecute { static void Main(string[] args) { Printdata p = new Printdata(); p.print(10); p.print(34.565); p.print("Hello"); Console.ReadLine(); } }}
动态多态性
动态多态性是通过抽象类和虚方法实现的
C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。
当一个派生类继承自该抽象类时,实现即完成。
抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。
请注意,下面是有关抽象类的一些规则:
- 不能创建一个抽象类的实例。
- 不能在一个抽象类外部声明一个抽象方法。
- 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
下面的程序演示了一个抽象类:
using System;namespace PolymorphismApplication{ abstract class Shape { public abstract int area(); } class Rectangle: Shape { private int length; private int width; public Rectangle( int a=0, int b=0) { length = a; width = b; } public override int area () { Console.WriteLine("Rectangle 类的面积:"); return (width * length); } } class RectangleTester { static void Main(string[] args) { Rectangle r = new Rectangle(10, 7); double a = r.area(); Console.WriteLine("面积: {0}",a); Console.ReadKey(); } }}
当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。
using System;namespace PolymorphismApplication{ class Shape { protected int width, height; public Shape( int a=0, int b=0) { width = a; height = b; } public virtual int area() { Console.WriteLine("父类的面积:"); return 0; } } class Rectangle: Shape { public Rectangle( int a=0, int b=0): base(a, b) { } public override int area () { Console.WriteLine("Rectangle 类的面积:"); return (width * height); } } class Triangle: Shape { public Triangle(int a = 0, int b = 0): base(a, b) { } public override int area() { Console.WriteLine("Triangle 类的面积:"); return (width * height / 2); } } class Caller { public void CallArea(Shape sh) { int a; a = sh.area(); Console.WriteLine("面积: {0}", a); } } class Tester { static void Main(string[] args) { Caller c = new Caller(); Rectangle r = new Rectangle(10, 7); Triangle t = new Triangle(10, 5); c.CallArea(r); c.CallArea(t); Console.ReadKey(); } }}
————————————————————————————–
C# 中的 override 作用
要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。
override可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。
不能重写非虚方法或静态方法。重写的基方法必须是 virtual、abstract 或 override 的。
override 声明不能更改 virtual 方法的可访问性。override 方法和 virtual 方法必须具有相同的访问级别修饰符。
您不能使用 new、static 或 virtual 修饰符来修改 override 方法。
重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。
C# 多态性总结
多态:一个接口多个功能。
- 静态多态性:编译时发生函数响应(调用);
- 动态多态性:运行时发生函数响应。
静态绑定(早期绑定):编译时函数和对象的连接机制。
两种技术实现静态多态性:函数重载/运算符重载。
函数重载:在同一范围内对相同函数名有多个定义,可以是参数类型或参数个数的不同,但不许只有返回值类型不同。
运算符重载
关键字 abstract 声明抽象类——用于接口部分类的实现(派生类继承抽象类时,实现完成)。抽象类包含抽象方法,抽象方法可被派生类实现。
抽象类规则:
- 不能创建抽象类的实例
- 不能在抽象类外定义抽象方法
- 不能把抽象类声明为sealed(类前带关键字sealed代表该类是密封类,不能被继承)
关键字virtual声明虚方法——用于方法在继承类中的实现(在不同的继承类中有不同的实现)。
抽象类和虚方法共同实现动态多态性。
注:继承类中的重写虚函数需要声明关键字 override,在方法参数传入中写(类名 形参名)例如 public void CallArea(Shape sh),意思是传入一个 shape 类型的类。
virtual 和 abstract
virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义。
- virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现。
- virtual可以被子类重写,而abstract必须被子类重写。
- 如果类成员被abstract修饰,则该类前必须添加abstract,因为只有抽象类才可以有抽象方法。
- 无法创建abstract类的实例,只能被继承无法实例化。
重载和重写
重载(overload)是提供了一种机制, 相同函数名通过不同的返回值类型以及参数来表来区分的机制——函数重载
重写(override)是用于重写基类的虚方法,这样在派生类中提供一个新的方法——动态多态性
————————————————————————————–
C# 运算符重载
运算符重载
您可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。
重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
例如,请看下面的函数:
public static Box operator+ (Box b, Box c){ Box box = new Box(); box.length = b.length + c.length; box.breadth = b.breadth + c.breadth; box.height = b.height + c.height; return box;}
上面的函数为用户自定义的类 Box 实现了加法运算符(+)。它把两个 Box 对象的属性相加,并返回相加后的 Box 对象。
运算符重载的实现
下面的程序演示了完整的实现:
using System;namespace OperatorOvlApplication{ class Box { private double length; private double width; private double heigh; public double getVolume() { return length * width * heigh; } public void setLength(double len) { length = len; } public void setWidth(double wid) { width = wid; } public void setHeigh(double hei) { heigh = hei; } public static Box operator+ (Box b, Box c) { Box box = new Box(); box.length = b.length + c.length; box.width = b.width + c.width; box.heigh = b.heigh + c.heigh; return box; } } class Tester { static void Main(string[] args) { Box Box1 = new Box(); Box Box2 = new Box(); Box Box3 = new Box(); double volume = 0.0; Box1.setLength(1.0); Box1.setWidth(1.0); Box1.setHeigh(1.0); Box2.setLength(2.0); Box2.setWidth(2.0); Box2.setHeigh(2.0); volume = Box1.getVolume(); Console.WriteLine("Box1's Volume is: {0}", volume); volume = Box2.getVolume(); Console.WriteLine("Box2's Volume is: {0}", volume); Box3 = Box1 + Box2; volume = Box3.getVolume(); Console.WriteLine("Box3's Volume is: {0}", volume); Console.ReadLine(); } }}
可重载和不可重载运算符
下表描述了 C# 中运算符重载的能力:
实例
针对上述讨论,让我们扩展上面的实例,重载更多的运算符:
using System;namespace OperatorOvlApplication{ class Box { private double length; // 长度 private double breadth; // 宽度 private double height; // 高度 public double getVolume() { return length * breadth * height; } public void setLength( double len ) { length = len; } public void setBreadth( double bre ) { breadth = bre; } public void setHeight( double hei ) { height = hei; } // 重载 + 运算符来把两个 Box 对象相加 public static Box operator+ (Box b, Box c) { Box box = new Box(); box.length = b.length + c.length; box.breadth = b.breadth + c.breadth; box.height = b.height + c.height; return box; } public static bool operator == (Box lhs, Box rhs) { bool status = false; if (lhs.length == rhs.length && lhs.height == rhs.height && lhs.breadth == rhs.breadth) { status = true; } return status; } public static bool operator !=(Box lhs, Box rhs) { bool status = false; if (lhs.length != rhs.length || lhs.height != rhs.height || lhs.breadth != rhs.breadth) { status = true; } return status; } public static bool operator <(Box lhs, Box rhs) { bool status = false; if (lhs.length < rhs.length && lhs.height < rhs.height && lhs.breadth < rhs.breadth) { status = true; } return status; } public static bool operator >(Box lhs, Box rhs) { bool status = false; if (lhs.length > rhs.length && lhs.height > rhs.height && lhs.breadth > rhs.breadth) { status = true; } return status; } public static bool operator <=(Box lhs, Box rhs) { bool status = false; if (lhs.length <= rhs.length && lhs.height <= rhs.height && lhs.breadth <= rhs.breadth) { status = true; } return status; } public static bool operator >=(Box lhs, Box rhs) { bool status = false; if (lhs.length >= rhs.length && lhs.height >= rhs.height && lhs.breadth >= rhs.breadth) { status = true; } return status; } public override string ToString() { return String.Format("({0}, {1}, {2})", length, breadth, height); } } class Tester { static void Main(string[] args) { Box Box1 = new Box(); // 声明 Box1,类型为 Box Box Box2 = new Box(); // 声明 Box2,类型为 Box Box Box3 = new Box(); // 声明 Box3,类型为 Box Box Box4 = new Box(); double volume = 0.0; // 体积 // Box1 详述 Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0); // Box2 详述 Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0); // 使用重载的 ToString() 显示两个盒子 Console.WriteLine("Box1: {0}", Box1.ToString()); Console.WriteLine("Box2: {0}", Box2.ToString()); // Box1 的体积 volume = Box1.getVolume(); Console.WriteLine("Box1 的体积: {0}", volume); // Box2 的体积 volume = Box2.getVolume(); Console.WriteLine("Box2 的体积: {0}", volume); // 把两个对象相加 Box3 = Box1 + Box2; Console.WriteLine("Box3: {0}", Box3.ToString()); // Box3 的体积 volume = Box3.getVolume(); Console.WriteLine("Box3 的体积: {0}", volume); //comparing the boxes if (Box1 > Box2) Console.WriteLine("Box1 大于 Box2"); else Console.WriteLine("Box1 不大于 Box2"); if (Box1 < Box2) Console.WriteLine("Box1 小于 Box2"); else Console.WriteLine("Box1 不小于 Box2"); if (Box1 >= Box2) Console.WriteLine("Box1 大于等于 Box2"); else Console.WriteLine("Box1 不大于等于 Box2"); if (Box1 <= Box2) Console.WriteLine("Box1 小于等于 Box2"); else Console.WriteLine("Box1 不小于等于 Box2"); if (Box1 != Box2) Console.WriteLine("Box1 不等于 Box2"); else Console.WriteLine("Box1 等于 Box2"); Box4 = Box3; if (Box3 == Box4) Console.WriteLine("Box3 等于 Box4"); else Console.WriteLine("Box3 不等于 Box4"); Console.ReadKey(); } }}
————————————————————————————–
C# 接口(Interface)
接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。
接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。
接口使得实现接口的类或结构在形式上保持一致。
抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。
定义接口:
接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。下面是一个接口声明的实例:
interface IMyInterface{ void MethodToImplement();}
以上代码定义了接口 IMyInterface。通常接口命令以 I 字母开头,这个接口只有一个方法 MethodToImplement(),没有参数和返回值,当然我们可以安装需求设置参数和返回值。
值得注意的是,该方法并没有具体的实现。
接下来我们来实现以上接口:
using System;namespace InterfaceApplication{ interface IMyInterface { void MethodToImplement(); } class InterfaceImplement : IMyInterface { static void Main(string[] args) { InterfaceImplement iTmp = new InterfaceImplement(); iTmp.MethodToImplement(); } public void MethodToImplement() { Console.WriteLine("MethodToImplement() called."); Console.ReadLine(); } }}
InterfaceImplementer 类实现了 IMyInterface 接口,接口的实现与类的继承语法格式类似: class InterfaceImplementer : IMyInterface
继承接口后,我们需要实现接口的方法 MethodToImplement() , 方法名必须与接口定义的方法名一致。
接口继承:
以下实例定义了两个接口 IMyInterface 和 IParentInterface。
如果一个接口继承其他接口,那么实现类或结构就需要实现所有接口的成员。
以下实例 IMyInterface 继承了 IParentInterface 接口,因此接口实现类必须实现 MethodToImplement() 和 ParentInterfaceMethod() 方法:
using System;interface IParentInterface{ void ParentInterfaceMethod();}interface IMyInterface : IParentInterface{ void MethodToImplement();}class InterfaceImplement : IMyInterface{ static void Main(string[] args) { InterfaceImplement iTmp = new InterfaceImplement(); iTmp.MethodToImplement(); iTmp.ParentInterfaceMethod(); Console.ReadLine(); } public void MethodToImplement() { Console.WriteLine("MethodToImplement() called."); } public void ParentInterfaceMethod() { Console.WriteLine("ParentInterfaceMethod() called."); }}
————————————————————————————–
参考资料: http://msdn.microsoft.com/zh-cn/library/ebca9ah3.aspx
- c#学习笔记4
- C#学习笔记4
- C#学习笔记(4)
- c#学习笔记4
- C#学习笔记4
- C# 学习笔记 4
- C#学习笔记(4)
- C#编程学习笔记4
- C#学习笔记 ----C#变量
- C#学习笔记(4)_C#教程
- C#学习笔记(4)_C#教程
- 学习笔记4 C# 编码问题
- c#学习笔记——4
- 《C#高级教程》学习笔记4 && 5
- C#寒假学习笔记(4)
- C#学习笔记 4 常量和变量
- C#学习笔记4-string和StringBuilder
- 38、我的C#学习笔记4
- 数据结构——线性表——链式存储结构——C++实现线性表
- Linux C 文件操作相关整理
- 请求筛选模块被配置为拒绝包含双重转义序列的请求。---该问题的解决办法之一
- 帮 IT 人减压放松的 10 个良心网站
- UVA
- C# 学习笔记 4
- 1021. 个位数统计 (15) PAT
- FAR 和 FRR
- **Android 图片处理系列:图片压缩处理
- $.ajax()方法详解
- 前缀、中缀、后缀表达式
- PAT 1001. A+B Format (20)
- quartz 企业级
- Java-多线程