一些主流编程语言:
C
:嵌入式硬件开发,操作系统底层C++
:游戏客户端,服务器,软件C#
:游戏客户端,服务器,软件,网站Java
:安卓,服务器,软件,网站JavaScript
:网站,服务器PHP
:网站,服务器Python
:爬虫,AI,机器学习,数据分析,自动化运维测试…SQL
:数据库Go
:服务器Objective-C
:mac,ios开发Swift
:mac,ios开发使用IDE:Visual Studio2019 Community
//输出后不跳行
Console.Write("xxx");
//输出后跳行
Console.WriteLine("xxx");
//检测玩家的一键输入
Console.ReadKey("xxx");
//检测玩家的一系列输入
Console.ReadLine("xxx");
折叠代码:
//折叠代码
#region myRegion
#endregion
变量:可以变化的容器
语法:变量类型 变量名 = 初始值;
一些常用变量类型:
有符号的整形变量:
四舍五入
//声明整形变量
int i = 666;
//声明浮点变量
float f = 0.11111111f;
//声明decimal数据
decimal de = 0.12345678910111235548m;
变量的本质:
变量中的存储单位所占字节数:(单位:字节byte)
变量的命名:
四不能:
二规范:
常量:
语法:const 变量类型 变量名 = 初始值
特点:
作用:声明一些不变的变量。
const float PI = 3.1415926f;
转义字符:
语法:\'
//定义字符串中有特殊字符
string str = "\'哈哈哈\'";
Console.WriteLine(str); //'哈哈哈'
\n
:换行
\\
:单斜杠
\t
:输出一个制表符
\b
:光标后退一格
\0
:空
\a
:警告音
类型转换:
隐式转换:不同类型之间自动转换(大范围装小范围,高精度存低精度)
注意,decimal不适用隐式转换原则。bool,string,char不存在隐式转换。
相同大类型转换:
//隐式转换
long l = 1;
int i = 1;
l = i;
不同大类型转换:
无符号无法装有符号数字。
有符号装无符号数字同需要符合范围完全覆盖原则。
浮点数可以转任何类型整数。
decimal不能隐式转换为float 和 double
但它可以存储整形。
char类型可以隐式转换为整形或浮点型,其转换后形成的是字符的 ASCII
码。
显示转换:
short s = 1;
int i = 1;
s = (short)i;
//将字符串转换成int
int i = int.Parse("123");
int a = Convert.ToInt32("12");
int a = Convert.ToInt32("1.4999");//1
int a = Convert.ToInt32(true);//1
short s5 = Convert.ToInt16("1");
long l5 = Convert.ToInt64("1");
float f = Convert.ToSingle("13.2");
bool bo = Convert.ToBoolean("true");
变量.ToString()
作用:
基本语法:try{ }catch{ }finally{ }
try
{
//希望进行异常捕获的代码块
//如果报错,则执行catch语块
}catch(Exception e)
{
//捕获异常(打印)
}
finally
{
//最后执行的代码,不管有没有出错,都会执行其中的代码
}
控制台补充API:
//读取输入但不在控制台显示
char c = Console.ReadKey(true).KeyChar;
//清空控制台内容
Console.Clear();
//关闭控制台
Environment.Exit();
随机数相关API:
//产生随机数对象
Random random = new Random();
//生成随机数
int i = r.Next();//生成一个非负随机数
i = r.Next(100); // 生成一个0~99的随机数
值类型:其他,结构体
引用类型:string,数组,类
ref 和 out区别:
作用:解决值类型和引用类型在函数内部 改变值 或者 重新声明能够影响外面传入的变量,让其也更改。
变长参数关键字params:
传入的参数都会参数在arr数组中,传入多少数字都不会报错。
params修饰的参数必须放在参数列表的最后位置且只能有一个。
用法示例
int Sum(params int[] arr)
{
}
//调用求和函数
int res = Sum();
int res1 = Sum(1,2,3,4,6,5);
重点内容:
栈溢出异常
。class Person
{
Person p = new Person(); //x
//构造函数的复用
public Person(int age){}
public Person(int age,string name):this(age){
//自动调用上面的age参数的函数
}
}
~Person(){}
垃圾回收机制(GC):识别哪些 没有被任何变量,对象引用的内容,会被回收释放。常见相关算法有:引用计数,标记清除,标记整理,复制集合。GC只负责堆(Heap)中内存的垃圾回收。而栈上的内存由系统自动管理,有自己的生命周期,会自动分配与释放。
c#中的垃圾回收机制详解:
分代算法:内存分为0代,1代和2代。新分配的内存都会被分配到0代,每次分配都可能(0代内存满时)会进行垃圾回收以释放内存。一次内存回收过程开始时,垃圾回收会认为堆中全是垃圾,会进行以下两步:
此外,大对象(83kb以上)总是被存在二代内存中,目的是 减少内存消耗,提高性能。
在游戏中,常常在Loading时会被调用,以提高玩家的体验
//手动触发垃圾回收
GC.Collect();
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
//自动属性(会自动生成一个成员变量height)
public float Height
{
get;
set;
}
class Person
{
private Person[] friends;
public Person this[int index]
{
get
{
return friends[index];
}
set
{
friends[index] = value;
}
}
}
class Person
{
public int this[int i,int j]{
get;set;
}
}
class Test
{
Person p = new Person();
p[0] = new Person();
}
//定义
static class Tools
{
public static void speakValue(this int value)
{
Console.WriteLine("为int拓展的方法" + value);
}
}
//使用
class Program
{
static void Main(string[] args){
int i = 10;
i.speakValue();//为int拓展的方法10
}
}
补充:如果拓展的方法与原有方法重名,则后续调用的方法仍然是原方法逻辑。
class Point
{
public int x;
public int y;
//点的相加
public static Point operator +(Point p1,Point p2)
{
Point p = new Point();
p.x = p1.x + p2.x;
p.y = p1.y + p2.y;
return p;
}
}
补充:算术运算符,条件运算符都可以被重载,逻辑运算符中仅有 逻辑非 可重载。条件运算符必须成对出现,有 > 一定有 < 。不能用ref 或 out关键字。
特性:
重点内容:
1.基础语法:class 类名 : 父类名
2.里氏替换原则:
– 概念:任何父类出现的地方,子类都可以代替(父类容器装载子类对象)
– 作用:方便对对象进行存储和管理
– 实例:
//Player是GameObject的子类(父类容器装载子类对象)
GameObject player = new Player();
– is关键字:
//判断player是不是Player类型
if (player is Player){}
– as关键字:
Player p = player as GameObject;
– is和as的联合运用:
if (player is Player)
{
Player p = player as Player; //返回null或者player对象
}
class Son:Father
{
//调用父类的i参数构造函数
public Son(int i) : base(i)
{
//...
}
}
4.万物之父与装箱拆箱
object:万物之父,可以用object容器装载一切类型的变量。
装箱拆箱:
装箱:用object存值类型数据
拆箱:把object里面的值转换出来
好处:不确定存储类型时可以使用,方便参数的传递与存储
坏处:存在内存的迁移,增加了性能消耗。
5.sealed关键字(密封类)
概念:让一个类不能再次被继承(绝育)
意义:加强面向对象程序设计的 规范性 结构性与安全性。
概念:多种状态,让继承统一父类的子类们执行相同方法时有不同表现。
目的:同一父类的对象执行相同行为(方法)有不同表现 。
作用:让同一个对象有惟一行为的特征。
重点内容:
class GameObject
{
public string name;
public virtual void Atk()
{
}
}
class Player : GameObject
{
public override void Atk()
{
base.Atk();
}
}
2.抽象类与抽象方法
– 抽象类概念:被abstract
修饰的类,不能被实例化,可以包含抽象方法。
– 抽象方法:没有方法体的纯虚方法,继承后必须去实现的方法
3.接口
– 概念:行为的接口规范
– 接口声明的规范:
— 1.不包含成员变量
— 2.只包含方法,属性,索引器,事件
— 3.成员不能被实现
— 4.成员可以不用写访问修饰符,不能是私有的
— 5.接口不能继承类,但是可以继承另一个接口
– 使用规范:
— 1.类可以继承多个接口,相当于行为合并
— 2.类继承接口后,必须实现接口中所有成员
– 特点:
— 1.他和类的声明类似
— 2.接口是用来继承的
— 3.接口不能被实例化,但是可以作为容器存储对象
重点内容:
1.命名空间namespace
– 基本语法:```namespace MyGame{}``
– 理解:类比Java中的包管理
2.类前面可以加哪些关键字
– 1.public:公有的
– 2.internal:只能在该程序集使用
– 3.abstract:抽象类
– 4.sealed:密封类
– 5.partial:分部类
3.命名空间总结:
– 1.命名空间是个工具包,用来管理类
– 2.不同命名空间张,可以有同名类
– 3.不同命名空间中互相使用,需要using引用或者指明出处
– 4.命名空间可以包裹命名空间
4.object类详解
– 1.bool Equals:判断两个对象是否相等,值类型比较是否相等,引用类型比较两个引用是否指向一个内存地址。
– 2.bool ReferenceEquals:专门比较引用类型的数据,传入值类型会始终返回false。
– 3.Object MemberwiseClone:获取浅拷贝对象,新对象引用变量和老对象一致。
5.string类与StringBuilder类
对比:SB相比string来说引用了容量的概念,减少了扩容的操作,使对一个字符串进行修改操作时性能提高了。当容量满溢时,SB会自动扩容(16->32)。
6.结构体和类的区别
– 1.二者最大的区别体现在存储空间上,结构体是值类型,存储在栈上,而类是引用类型,存储在堆上。结构体具有OOP中的封装特性,但不具备继承和多态,因此大大减少了其使用频率。
– 2.一些细节区别:总结
1.结构体是值类型,类是引用类型
2.结构体存储在栈中,而类存储在堆中
3.结构体成员不能使用 protected关键字,而类可以
4.结构体成员变量不能声明初始值,而类可以
5.结构体不能申明午餐构造函数,类可以
6.结构体申名有参函数构造后,无参构造不会被顶替
7.结构体不能什么析构函数,类可以
8.结构体不能被继承,类可以
9.结构体需要再构造函数中初始化所有成员变量,类随意
10.结构体不能被static修饰,类可以
11.结构体不能再自己内部声明和自己一样的结构体变量,类可以
– 3.结构体特别之处
结构体可以继承接口,接口是行为的抽象
1.都可以被继承
2.都不能直接实例化
3.都可以包含方法声明
4.子类必须实现未实现的方法
5.都遵循里式转换原则
– 2.区别:
1.抽象类可以有构造函数,接口不行
2.抽象类只能被单一继承,接口可以被继承多个
3.抽象类可以有成员变量,接口中不能
4.抽象类可以申明成员方法,虚方法,抽象方法,接口中只能声明未实现的抽象方法
5.抽象类方法可以使用访问修饰符,接口中建议不写,默认public
– 3.如何选择使用
1.表示对象的用抽象类,表示行为拓展的用接口
2.不同对象拥有的共同方法,可以使用接口来实现
3.动物是一类对象,选择抽象类,而飞翔是一个行为,选择使用接口
本质:本质是 一个 Object 类的数组。
语法:ArrayListList a = new ArrayList();
查询工具类:https://learn.microsoft.com/zh-cn/
补充:ArrayList本质是一个Object数组,故在存储值类型数据时存在大量装箱拆箱操作,尽量少用该容器,之后会学习更好的数据容器。
本质:本质也是 Object 类的数组,Stack是遵循 先进后出 的存储规则,而Queue遵循 先进先出 的存储规则。
语法:
Stack stack = new Stack();
Queue queue = new Queue();
API不在此列举,养成自主查询文档的习惯!!!
补充:同样涉及到许多装箱拆箱操作,会降低效率!
本质:基于哈希代码组织起来的 键值对存储。提高查询效率。
语法:Hashtable hashtable = new Hashtable();
重点:
hashtable["111"]
//遍历所有键值
//方案1
foreach(object item in hashtable.Keys)
{
item;hashtable[item]
}
//方案2
foreach(object item in hashtable.Values){}
//方案3
foreach(DictionaryEntry item in hashtable)
{
item.Key,item.Value;
}
//迭代器遍历
IDictionaryEnumerator myEnumerator = hashtable.GetEnumerator();
bool flag = myEnumerator.MoveNext();
while(flag)
{
myEnumerator.Key;
myEnumerator.Value;
flag = myEnumerator.MoveNext();
}
概念:实现了类型参数化,达到代码复用的目的
泛型类和接口;
泛型方法:
public T Test<T>()
{
return default(T);
}
作用:
作用:让泛型的类型有一定限制
基本用法:
where 泛型字母 : struct
where 泛型字母 : class
where 泛型字母 : new()
where 泛型字母 : 类名
where 泛型字母 : 接口名
where 泛型字母 : 另一个泛型字母
多个泛型约束:
class Test8<T,K> where T : class,new() where K:struct{}
本质:可变类型的泛型数组
语法:List
增删改查API自查文档!!!
补充:查的操作同样可使用数组类似的下标法取出。
本质:拥有泛型的 Hashtable
声明:Dictionary
补充:
foreach(KeyValuePair<int,string> item in dictionary)
{
item.Key,item.Value;
}
定义:方法的容器。可以理解为表示函数的变量类型。用来存储,传递方法。
本质:本质上是一个类,用来定义方法的类型,不同函数必须对应各自格式(参数与返回值)一致的委托。
语法:访问修饰符 delegate 返回值 委托名(参数列表);
重点内容:
//定义一个int参数的无返回值的委托
delegate void MyFun(int k);
class Solution
{
MyFun myfun;
public void haha(int param){...}
public void hehe(int param){...}
static void Main(string[] args)
{
//添加委托
myfun += haha;
myfun += hehe;
//调用
myfun(1);
}
}
Action action = Fun;
action += Fun2;
action();
Func:泛型返回值无参数委托
Func<string> funcString = Fun4;
Func<int> funcInt = Func5;
Action<>:可以传n个参数无返回值函数委托
Action<int,string,bool,K,V> action2 = Fun6;
Func<>:可以传n个参数有返回值的函数委托
//最后一个参数为返回值,带out关键字
Func<int ,string,bool,K,V,int> action3 = Fun7;
概念:基于委托,是委托的安全包裹,让委托更具有安全性。是一种特殊的变量类型。
语法:访问修饰符 event 委托类型 事件名
使用:
概念:没有名字的函数,主要配合委托和事件使用
语法:delegate (参数列表)
样例
:
//声明匿名函数
Action a = delegate ()
{
}
a();
a.Invoke();
缺点:添加到委托或事件容器中不记录,无法单独移除。
概念:匿名函数的简写,与委托或者事件配合使用。
语法:(参数列表)=>{}
使用:
Action a = () => {...}
a();
//甚至参数类型可以省略,与委托容器一致
Action<int> a2 = (value) => {...}
缺点:和匿名函数一样。
补充:
匿名函数排序案例:
//声明一个List
List<Item> itemList = new List<Item>();
itemList.Add(...);
itemList.Sort(delegate (Item a ,Item b) => {
if (a.id > b.id)
{
return
}
});
//lambda表达式写法
itemList.Sort(( a , b )=>{
//升序
return a.id > b.id ? 1 : -1;
})
协变:和谐的变化,自然的变化,里氏替换原则,子类转父类。父类泛型委托装子类泛型委托。
逆变:逆常规变化,父类转子类。子类泛型委托装父类泛型委托。
作用:
进程:操作系统下 可以进行许多进程(前台,后台)。进程之间相互独立运行,互不干扰。也可以相互访问,操作…
线程:操作系统能够运算调度的最小单位。其被包含在进程之中,是进程的实际运作单位。一个进程可以并发多个线程。
语法:所需类:using System.Threading;
声明:Thread t = new Thread(无参无返回值委托函数);
开启线程:t.Start();
设置后台线程:t.IsBackground = true;
中止线程:t.Abort(); t = null
线程休眠:Thread.Sleep(1000);
//线程休眠1s
锁机制lock:
lock(引用变量){...}