一、类
- 如果要访问类中的成员,需要使用 . 点运算符,点运算符链接了对象的名称和成员的名称。
- 类的构造函数在创建类的新对象时执行,构造函数名称与类的名称相同,没有任何返回类型。默认的构造函数没有任何参数,如果有需要也可以自己创建一个带参数的参数化构造函数。
- 类的析构函数当类的对象超出范围时执行。析构函数是在类的名称前面加一个~,无返回值也没有任何参数。析构函数用于在结束程序之前释放资源。
- 使用static关键字可以定义静态的类成员,无论有多少类的对象创建,只会有一个静态成员的副本。静态变量可以用于定义常量,它们的值可以通过直接调用类而不是创建类的实例获取。
- 如果一个成员函数声明为static,则它只能访问静态变量。
using System;
namespace BoxApplication
{
//类的定义
class Box
{
private double length; // 长度
private double breadth; // 宽度
private double height; // 高度
public static int num = 0; //定义静态成员
//参数化构造函数
public Box( double len, double bre, double hei)
{
Console.WriteLine("对象已创建");
length = len;
breadth = bre;
height = hei;
}
~Box()
{
Console.WriteLine("对象已删除");
}
public void count()
{
num ++;
}
public int get_num()
{
return num;
}
public void setLength( double len )
{
length = len;
}
public void setBreadth( double bre )
{
breadth = bre;
}
public void setHeight( double hei )
{
height = hei;
}
public double getVolume()
{
return length * breadth * height;
}
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box(6.0, 7.0, 5.0);
Box Box2 = new Box(12.0, 13.0, 10.0);
double volume; // 体积
volume = Box1.getVolume();
Console.WriteLine("Box1 的体积: {0}" ,volume);
Box1.count();
Box1.count();
Console.WriteLine(Box1.get_num());
// Box2 的体积
volume = Box2.getVolume();
Console.WriteLine("Box2 的体积: {0}", volume);
Box2.count();
Box2.count();
Console.WriteLine(Box2.get_num());
Console.ReadKey();
}
}
}
代码运行结果:
对象已创建
对象已创建
Box1 的体积: 210
2
Box2 的体积: 1560
4
二、继承
C#中派生类的定义如下:
<访问修饰符> class <基类>
{
…
}
class <派生类> : <基类>
{
…
}
派生类继承了基类的成员变量和成员方法,C#不支持多重继承。
三、多态性
多态性分为静态多态性和动态多态性。在静态多态性中,函数的相应是在编译中发生的;而在动态多态性中,函数的相应是在运行时发生的。
静态多态性可以使用函数重载和云算法重载实现。
函数重载:可以在同一范围内对多个相同的函数名有多个定义。但是函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数的个数不同。
动态多态性主要通过抽象类和虚方法实现。
- 使用关键字abstract创建抽象类。
- 当有一个在基类中的函数需要在继承类中实现时,可以使用虚方法,使用关键字virtual声明。
抽象类:
using System;
namespace PolymorphismApplication
{
abstract class Shape
{
abstract public int area(); //定义抽象类
}
class Rectangle : Shape //类Rectangle继承Shape类
{
private int length;
private int width;
public Rectangle( int a, int b)
{
length = a;
width = b;
}
public override int area ()
{
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();
}
}
}
虚方法:
using System;
namespace PolymorphismApplication
{
class Shape
{
protected int width, height;
public Shape( int a, int b)
{
width = a;
height = b;
}
public virtual int area() //定义虚方法
{
return 0;
}
}
class Rectangle: Shape //类Rectangle继承类Shape
{
public Rectangle( int a, int b): base(a, b) //定义部分继承Shape类中的
{
}
public override int area () //计算面积
{
return (width * height);
}
}
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);
c.CallArea(r);
Console.ReadKey();
}
}
}
代码运行输出:
面积:70
四、接口
接口定义了属性、方法和事件。接口只包含了对它们的声明,它们的定义在派生类中。接口提供了派生类应遵循的标准结构。接口使得实现接口的类或结构在形式上保持一致。
接口使用interface关键字声明,默认为public
interface IMyInterface
{
void MethodToImplement();
}
接口命令通常以I开头,上述声明中该接口只有一个方法MethodToImplement()
接口继承的语法与类继承的语法类似。如果一个接口继承其他接口,那么实现类或结构就需要实现接口中的所有成员。
五、命名空间
命名空间提供了让一组名称与其他名称分隔开的方式。不同命名空间声明的类名字相同并不冲突。
如果在另一个命名空间中需要使用到其他命名空间的类,需要<命名空间名> . <类名>来实例。也可以直接使用using该命名空间,便可以在所有命名空间中直接使用里面的类。命名空间允许嵌套。
六、预处理器指令
预处理器指令指导编译器在实际编译开始之前对信息进行预处理,常用于调试。
所有预处理器指令都是以#开始,不以;结束。同一行中,只有空白字符可以出现在预处理器之前
define预处理器
#define用于创建定义一个符号,然后可以通过符号传递给#if指令的表达式,表达式将返回true
条件指令
分为if,elif,else,endif
七、异常处理
C#异常处理建立在4个关键词上:try,catch,finally和throw
- try:用于标识一个引起异常的语句,后跟一个或多个catch块
- catch:用于表示异常的捕获
- finally:用于执行给定的语句,无论异常是否抛出都会执行
- throw:当问题出现时,使用throw来抛出一个异常
try
{
// 引起异常的语句
}
catch( ExceptionName e1 )
{
// 错误处理代码
}
catch( ExceptionName e2 )
{
// 错误处理代码
}
catch( ExceptionName eN )
{
// 错误处理代码
}
finally
{
// 要执行的语句
}
异常类 | 描述 |
---|---|
System.IO.IOException | 处理IO错误 |
System.IndexOutOfRangeException | 处理方法指向超出范围的数组索引错误 |
System.Array.TypeMismatchException | 处理数组类型不匹配错误 |
System.DivideByZeroException | 处理除以零的错误 |
System.InvalidCastException | 处理类型转换的错误 |
System.OutOfMemoryException | 处理空间内存不足的错误 |
System.StackOverflowException | 处理栈溢出的错误 |
八、多线程
线程可以通过System.Threading.Thread类的对象创建,生命周期分几种状态:
- 未启动状态:被创建但是Start方法未被调用
- 就绪状态:准备好运行,等待CPU周期
- 不可运行状态:调用了Slepp方法、调用了Wait方法或通过IO操作阻塞
- 死亡状态:已完成执行或被中止
属性 | 描述 |
---|---|
CurrentThread | 获取当前正在运行的线程 |
IsAlive | 显示当前线程的执行状态 |
Priority | 显示线程的调度优先级 |
ThreadState | 显示当前线程的状态 |
方法:
- public void Abort():中止线程
- public void Start():开始一个线程
- public static void Sleep(int milliseconds Timeout):让线程暂停一段时间
在定义一个线程的时候,可以使用ThreadStart()这个委托,这个委托指定了线程的方法,定义在()内。
中止线程的时候,可以使用异常捕获threadabortexception
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
try
{
Console.WriteLine("Child thread starts");
// 计数到 10
for (int counter = 0; counter <= 10; counter++)
{
Thread.Sleep(500); //每次暂停0.5s
Console.WriteLine(counter);
}
Console.WriteLine("Child Thread Completed");
}
catch (ThreadAbortException e)
{
Console.WriteLine("Thread Abort Exception");
}
finally
{
Console.WriteLine("Couldn't catch the Thread Exception");
}
}
static void Main(string[] args)
{
//定义一个线程,名字为childref,线程使用方法CallToChildThread
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("Creating the Child thread");
Thread childThread = new Thread(childref); //线程创建
childThread.Start(); //线程开始运行
Thread.Sleep(2000); //线程暂停一段时间
Console.WriteLine("Aborting the Child thread");
childThread.Abort(); //中止线程
Console.ReadKey();
}
}
}
代码运行结果:
Creating the Child thread
Child thread starts
0
1
2
Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception