一、《菜鸟教程》
1.0数据类型
1.1判断
实际上c#的判断符有两种,一个是if-else,另一个是switch-case-break。下图是一个比较神奇的运算方法,我估计unity里面大概率是没法用。
1.2循环
1)while循环
先判断条件是否满足,然后进行循环体内的代码块。
有可能一次循环体都不进行。
2)for循环
首先初始化(init)条件、变量和增长相关的信息——>
执行判断语句和如下代码块——>
increment增加条件变量——>
当条件不满足的时候执行下一段代码。
3)foreach循环
思路与for循环相似,但使用foreach可以迭代数组或者一个集合对象。
以下代码有三个部分:
- 通过 foreach 循环输出整型数组中的元素。
- 通过 for 循环输出整型数组中的元素。
- foreach 循环设置数组元素的计算器。
4)循环控制语句
- break:终止循环,直接执行循环的下一条语句。
- continue:跳过循环主体,直接开始下一次测试条件。
1.3封装
定义:封装是把一个或多个项目封闭在一个物理的或者逻辑的包中。
手段:使用访问修饰符定义类成员的范围和可见性。
1)public访问修饰符
2)private
3)protected
Protected 访问修饰符允许子类访问它的基类的成员变量和成员函数,本质上这个修饰符是用于class的继承相关的部分(待验证)。
见(Protected章节)
4)internal
没太搞懂,原文定义如下:带有 internal 访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问。
1.4方法
1)方法的定义
一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。
2)定义一个方法
本质上是在生命它结构的元素——
(Parameter List) { Method Body; }
Access Specifier:修饰符是否公开决定了这个方法对其他类的可见性
Return Type:返回值类型,如果方法没有返回值的话,请写void
Method Name:大小写敏感的唯一标识符
Parameter List:该参数是用来传递和接收方法的数据,指方法的参数类型、顺序、数量
Method Body:主体方法代码块
观察上式可发现:如何使用带有返回值的方法。
4)递归方法调用
例如阶乘
1.5参数传递
方式 | 描述 |
---|---|
值参数 | 这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。在这种情况下,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。 |
引用参数 | 这种方式复制了实参的内存位置给形参,当形参的值发生变化时,同时也改变实参的值。 |
输出参数 | 可以使用输出参数来从函数中返回两个值(?)。之后输出参数会把方法输出的数据赋给自己。如下图,形式参数x不论有没有预先设定的值,执行方法后,都会变成5. |
1.6可空类型
就是不知道Unity里能不能用……我真实没懂这玩意有啥用啊
0)单问号和双问号
单问号(?)用于对int double bool等无法直接赋值为null的数据类型进行null的赋值。
双问号(?)用于判断一个变量在为 null 的时候返回一个指定的值。
1.6数组
与Python的列表仍存在区别
1)定义
数组是一个同一类型变量的集合。所有的数组都是由连续的内存位置组成的。
2)声明数组
datatype [] arrayName ;
- datatype 指定数组元素的类型
- [] 指定数组的大小
-
3)初始化数组
声明一个数组不会在内存中初始化数组。当初始化数组变量时,才可以赋值给数组。
数组是一个引用类型,所以需要使用new来创建实例。4)赋值给数组
方法有很多:
通过索引号赋值给单独的数组元素
- 声明数组的同时给数组赋值
- 创建并初始化一个数组(可省略大小)
- 赋值一个数组变量到另一个数组变量中(弱辅复制,实际指向同一个源)
5)访问数组元素
需要使用带索引的数组名称,实际上就是如下:
double salary = balance[9] ;
6)使用foreach遍历数组
7)【数组应用】多维数组
二维数组定义:一个二维数组可以被认为是一个带有 x 行和 y 列的表格。数组中的每个元素是使用形式为a[ i , j ]的元素名来标识。
初始化二位数组:多维数组可以通过在括号内为每行指定值来进行初始化。
访问二维数组元素:使用下标(行索引和列索引)
8)【数组应用】交错数组
交错数组是数组的数组,实际上是一个特殊的二维数组。
例如,一个带有int值的交错数组……
9)【数组应用】传递数组给函数
10)【数组应用】参数数组
11)【数组应用】Array类
1.7字符串
1)创建字符串对象
- 给String变量指定一个字符串
- 使用String类构造函数
- 使用(+)
2)一些实例
3)应该还有一些,但是再说了
1.8结构体
1.9枚举(Enum)
1)定义
枚举是一组确定的命名整形常量。枚举类型是使用enum关键字声明的。
2)声明enum变量
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
如上是一个用逗号分隔的标识符列表。枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0。
例如:https://blog.csdn.net/ldy597321444/article/details/50676010
例如:https://blog.csdn.net/u014361280/article/details/115945198
1.10类Class
1)定义
实际上定义了一个数据类型的蓝图。对象是类的实例。构成类的方法和变量称为类的成员。
明确几个概念:访问标识符、数据类型、返回类型、点运算符……
2)成员函数和封装
类的成员函数是一个在类定义中有它的定义或原型的函数,就像其他变量一样。作为类的一个成员,它能在类的任何对象上操作,且能访问该对象的类的所有成员。
当我们将类实例化以后,我们实际上得到了很多以类为蓝图生产出的游戏对象。
成员变量是对象的属性(从设计角度),且它们保持私有来实现封装。这些变量只能使用公共成员函数(public的函数)来访问。
3)构造函数
类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。构造函数的名称与类的名称完全相同,它没有任何返回类型。
事实上,在Unity中尽量不要使用构造函数,因为它会和 Start() 或者 Awake() 冲突。
4)析构函数
- 析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
Unity中基本不用
5)静态成员
- 我们可以使用 static 关键字把类成员定义为静态的。当我们声明一个类成员为静态时,意味着无论有多少给类的对象被创建,都只会有一个该静态成员的副本。关键字 static 意味着类中只有一个该成员的实例。静态变量用于定义常量,因为它的值可以通过直接调用类而不需要创建类的实例来获取。
- 静态变量可以在成员函数或者类的外部进行初始化,也可以在类的定义内部初始化。
1.11继承
1)基类和派生类
- 当创建类时,我们一般设计新的类,继承已有的类的成员——已有的类是基类,新的类是派生类。一个类可以派生自多个类或者接口,这意味着它可以从多个基类或接口继承数据和函数。
2)基类的初始化
- 父类对象应当在子类对象之前被创建和初始化。
如上图红圈,tabletop类是rectangle的子类,两个变量需要回到父类进行计算。
3)多重继承
c#不支持多重继承,但是可以用接口达到相似效果。
-
1.12多态性
在面向对象的编程中,所谓的多态性往往表现为指的是一个接口,多个功能。在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object。在编译时,函数和对象的连接机制被称为静态绑定,c#有两种:函数重载和运算符重载。
1)函数重载(静态重载)
在某个范围内对相同的函数名有多个定义:参数列表中的参数类型不同/参数个数不同随意。
2)运算符重载(动态重载)
- 简单来说是可以自定义c#中内置的运算符。重载运算符是具有特殊名称的函数,是通过关键字operator后跟运算符的符号类定义的。重载运算符有返回类型和参数列表。
3)动态多态性(动态重载)
-
(1)抽象类——类抽象+方法抽象
在c#中使用关键字abstract创建抽象类,当一个派生类继承自此抽象类时,就完成了实现(听起来好像类的实例化啊)。抽象类包含抽象方法,抽象方法可以被派生类实现,事实上派生类中的抽象方法是原抽象方法的重载(override)。
(2)虚方法——普通类+抽象方法
- 当有定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法由关键字virtual声明,在运行时调用虚方法。事实上,在重载并调用虚方法以后,虚方法中的代码块也会被执行。
- 以下代码在执行的时候,只需要实例化对象.Draw(); 即可
这个地方菜鸟教程网站上的例子还是写的很清楚的。
1.13接口(interface)
1)前置概念
- 接口和类相似,定义了所有类继承接口时应该遵循的语法合同。接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。
- 抽象类在某种程度上和类接口相似,但是,它们的区别也同样明确:
- 接口是对动作的抽象(能否吃饭),抽象类是对根源的抽象(是否为动物);
- 因此一个类只能继承一个类,而一个类可以继承多个接口;
- 当关注一个事物的本质的时候,用抽象类;当关注一个操作的时候,用接口;
2)定义接口
接口使用interface声明,与类的声明类似。如果一个接口继承其他接口,那么实现类或结构就需要实现所有接口的成员。以下实例 IMyInterface 继承了 IParentInterface 接口,因此接口实现类必须实现 MethodToImplement() 和 ParentInterfaceMethod() 方法:
关于Unity内的实现:https://blog.csdn.net/jk823394954/article/details/50421829如果是初学者,剩下的可以不看了……
1.14命名空间
1.15c#预处理器指令
1.16正则表达式
可以用于操作字符串,匹配指定特征的字符串。后面要用的时候再看罢。
1.17c#对异常的处理
除了《菜鸟教程》以外的一些参考:https://blog.csdn.net/qq_35587645/article/details/106664047
1.18特性(Attribute)
在c#中,特性是一种很奇怪的存在,但在Unity中,特性的功能基本上是由Unity的API所确定的。具体参考如下文章。
https://www.jianshu.com/p/f2df8df865bc
1.19反射(Reflection)
建议直接看这篇文档,Unity中的反射跟c#中的存在已经有所不同。
https://www.jianshu.com/p/2f0cfdf116c8
1.20属性(Property)
1)定义与特征
属性(Property) 是类(class)、结构(structure)和接口(interface)的命名(named)成员。类或结构中的成员变量或方法称为 域(Field)。
属性(Property)是域(Field)的扩展,且可使用相同的语法来访问。它们使用 访问器(accessors) 让私有域的值可被读写或操作。属性(Property)不会确定存储位置。相反,它们具有可读写或计算它们值的 访问器(accessors)。例如,有一个名为 Student 的类,带有 age、name 和 code 的私有域。我们不能在类的范围以外直接访问这些域,但是我们可以拥有访问这些私有域的属性。
2)访问器
属性(Property)的访问器(accessor)包含有助于获取(读取或计算)或设置(写入)属性的可执行语句。访问器(accessor)声明可包含一个 get 访问器、一个 set 访问器,或者同时包含二者。
二、刷题
leetcode、codewar之类……