一、调试和错误处理

1、错误(bug)

代码中总会出现不可避免的错误,比如变量名写错、未按规定定义函数等等,称为语义错误;书写代码时逻辑有瑕疵,称为逻辑错误。

2、调试

①Console.WriteLine()或者Console.Write()输出 ②Debug.Log()、Debug.LogError()、Debug.LogWarn()输出 ③中断(Debug)模式下的调试Console.ReadLine(),中断模式是指我们可以暂停程序的执行,然后查看程序中的状态,也可以让程序继续执行。 如何让程序中断:断点(双击打在数字行号前,遇到断点程序暂停,快捷键F9,或右键单击插入断点) 运行程序,会在断点出现暂停 逐语句和逐过程

3、错误(异常)处理

异常:在运行期间代码中产生的错误。 对可能发生错误的地方采取预防措施,并编写弹性代码来处理可能会发生的致命错误,异常处理又称为异常捕捉,常用try…catch…finally语句。

try//存放要捕捉异常的代码

{

//当这里面有一行错误,后续的不会继续执行,直接进入catch

}catch(){//要捕捉的异常类型catch语句可以有多个

.....//出现该异常的时候怎么处理

}finally{

.....//不管出现异常没,都会执行

}

常见异常的类型: 用循环解决多次出错的问题,通break进行跳出循环

二、面向对象编程(OOP)

面向对象编程,又称模块化编程。为了让程序更加清晰,把程序中的功能进行模块化划分,每个模块提供特定的功能,而且每个模块都是孤立的,这种模块化变成提供了非常大的多样性,大大提高了重用代码的几率。

三、类

1、类

对象: 类创建的变量。 类: 实际上是创建对象的模版,每个对象都包含数据,并提供了处理和访问数据的方法。类定义了类的每个对象(实例)包含了什么数据和功能。类中的数据和函数称为类的成员。 创建新的类的步骤: 创建完成后还是在刚才的项目下(命名空间下),只是多了一个新的类。

2、类的成员

①数据成员:包含类的数据——字段、常量、和事件的成员。 ②函数成员:提供了操作类中数据的某些功能(方法、属性、构造方法和终结器(析构方法)、运算符和索引器)

class Customer

{

//定义数据成员(成员变量)

public String name;

public String address;

public int age;

public String creatTime;

//定义函数成员(成员方法)

public void Show()

{

Console.WriteLine("name:" + name);

Console.WriteLine("address:" + address);

Console.WriteLine("age:" + age);

Console.WriteLine("creatTime:" + creatTime);

}

}

3、用类创建对象

//利用类创建对象,c1就是对象名

Customer c1 = new Customer();

//可以分为以下两步

Customer c2;//声明对象

c2 = new Customer();//实例化对象,没有实例化就是空对象

//赋值

c1.name = "QDD";

c1.address = "四川";

c1.age = "18";

c1.creatTime = "2023";

//调用类中的方法

c1.show();

四、构造函数

在构造对象的时候,对象的初始化工作过程是自动完成的,但是在初始化对象的过程中需要做一些额外的工作,例如需要初始化对象存储的数据,构造函数就是用于初始化数据的函数。 声明基本的构造函数的语法就是声明一个所在类同名的方法,但是该方法没有返回值(没有返回值所以不用声明类型)。

①无参构造:

②带参构造:

③成员变量与构造函数参数重名的情况

五、属性

在原本的类中,我们对私有成员变量设置和获取值需要get和set函数,会使代码变得复杂:

//定义数据成员(成员变量)

private String name;

private String address;

private int age;

private String creatTime;

public void SetAge(int age)

{

this.age = age;

}

public int GetAge()

{

return age;

}

//在另一个类中调用

Customer li = new Customer();

li.SetAge(18);

li.GetAge();

①属性:

//属性

private int age;

//属性一般与成员变量同名,只是将手写字母大写

public int Age

{

//属性中包含两个块,get块相当于get函数,set块相当于set函数,又称访问器。可以只有一个get或者只有一个set.

get

{

return age;

}

set//value参数

{

age = value;

}

}

//在另一个类中

Customer li = new Costomer();

li.Age = 18;

console.WriteLine(li.Age);

②自动实现的属性:

//在代码中没有age这个数据

//private int age;

//系统会自动创建数据成员

public int Age{get;set};

③匿名类型: 根据变量值确定它的值的类型。

var 变量名 = 变量值;

六、继承

1、继承

很多类中有相似的数据,比如在一个游戏中,有boss类、小怪类Enemy,这些类他们有很多相似的属性,但是也有不同的,这个时候可以使用继承来让这两个类继承自同一个类(基类或父类)。 ①新建两个类,一个子类,一个基类 ②将子类继承自基类 ③使用尝试

class BaseClass

{

public void Founction1()

{

Console.WriteLine("这是功能1");

}

public void Founction2()

{

Console.WriteLine("这是功能2");

}

}

class Program

{

static void Main(string[] args)

{

BaseClass bc = new BaseClass();

bc.Founction1();

bc.Founction2();

}

}

使用子类去调用,结果是与基类调用相同的:

class Program

{

static void Main(string[] args)

{

//BaseClass bc = new BaseClass();

//bc.Founction1();

//bc.Founction2();

DriveClass dc = new DriveClass();

dc.Founction1();

dc.Founction2();

}

}

④this和base关键字(区别子类和父类) this用于访问子类里面的变量和方法。 base用于引用访问父类的变量和方法。

2、重写方法

继承之后,子类的功能和父类的功能不太相同,就需要进行重写方法。有虚方法和隐藏方法两种形式。

(1)虚方法

①在父类中将需要重写的方法名前加上关键字“virtual”。

②在子类中在正在重写的方法前加上关键字“override”。 调用,可以看到是子类重写的move()方法

(2)隐藏方法

隐藏方法的父类方法中,不作改变,相当于直接重写。而对于子类的重写方法中需要加上关键字"new"。

七、类相关

1、抽象类

C#允许把类和函数声明为abstract。抽象类不能实例化,抽象类可以包含普通函数和抽象函数,抽象函数只有函数定义没有函数体,显然抽象函数本身也是虚拟的virtual。类是一个模版,抽象类就是一个不完整的模版。如:定义一个抽象的敌人类: 此时我们发现如果想继承该抽象类就会报错,解决办法为实现该抽象类中的抽象方法。

2、密封类和密封方法

C#允许把类和方法声明为sealed。密封类不能被继承,密封方法不能被重写。被声明为sealed必须是已经被重写的方法。

3、派生类的构造函数

(1)在子类中调用父类的默认构造函数(无参),会先调用父类的,然后是子类的。 运行结果: ②调用有参数的构造函数。 另:自动生成构造函数的步骤:定义一个变量——》(右键)快速操作和重构——》生成构造函数——》选择成员——》确定

八、接口

一般情况下,接口只能包含方法,属性,索引器和事件的声明。接口不能有构造函数,也不能有字段,也不允许运算符重载。 ①定义(用I打头,代表一个接口) 定义一个接口和定义一个抽象类在方法上完全相同,但不允许提供接口中任何成员的实现方式。接口定义中不允许声明成员的修饰符,接口成员都是公有的。

②实现接口要实现接口里面所有的方法 ③用接口声明对象

Interface fly;

fly = new Fly();

//这时fly就有了Fly的功能

fly.Fly();

fly.Flyer();

④接口的继承 当Interface2继承了Interface1,在实现Interface2的方法时,也要实现Interface1的所有方法。

九、集合类

我们定义很多类型一样的数据,以前一般用数组存放,但是数组大小确定,存放数据量有限。如果我们存放很多类型一样的数据,比如游戏得分,我们可以用集合类来进行管理,比如列表List.

1、列表

①创建:列表可以存储任何类型的数据,但是我们再创建时需要指定创建的列表存放什么类型。在list后面加上尖括号加上类型——泛型。

//在创建后面加上大括号,中间加上数据可以增添初始值

List list = new List() { 111,156,178};

//增加

list.add(100);

//访问、修改——索引(和数组一样)

Console.WriteLine(list[3]);

//遍历,for循环\foreach循环

//设置列表容量

list.Capacity = 100;

//列表数据的个数list.Count;

//插入Insert:在第3个数前插入数字800

list.Insert(3,800);

//移除Remove:移除值为32的数,假如列表中有两个32只移除第一个

list.Remove(32);

//查询某个数在列表中的索引位置

list.IndexOf(32);

//从后往前进行查找

list.LastIndexOf(32);

//对列表进行排序(从小到大)

list.Sort();

十、泛型

通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的应用。 ①定义

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace CollectionAbout

{

class Program

{

static void Main(string[] args)

{

ClassA a = new ClassA(15,20);

Console.WriteLine(a.GetSum());

}

}

class ClassA

{

private int a;

private int b;

public ClassA(int a,int b)

{

this.a = a;

this.b = b;

}

public int GetSum()

{

return a + b;

}

}

}

通过该代码我们发现,如果此时我们要相加两个double类型的数据,仅仅只需要更改数据类型和方法名称了,但是确实需要复制一整段代码,很繁琐。这个时候可以使用泛型。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace CollectionAbout

{

class Program

{

static void Main(string[] args)

{

//此时的<>中必须指明类型

ClassA a = new ClassA(15,20);

Console.WriteLine(a.GetSum());

}

}

class ClassA //type int string double

{

private T a;

private T b;

public ClassA(T a,T b)

{

this.a = a;

this.b = b;

}

public T GetSum()

{

dynamic num1 = a;

dynamic num2 = b;

dynamic result = num1 + num2;

return (T)result;

}

}

}

十一、其他

1、Tostring()方法

将一个数据转化为字符串

Program p = new Program();

Console.WriteLine(p.ToString());

2、Equals()方法

比较的是引用地址,如果要比较的是地址之间的数值就需要重写Euqals方法。

int a = 12;

int b = 34;

Console.WriteLine(a.Equals(b));

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。