转自擅码网并修改
(黄色为最重要)
1.ToUpper()
作用:将字符转换成大写形式,仅对字母有效。返回值是转换后的字符串。
使用:字符串变量或常量.ToUpper();
例如:"hh".ToUpper();
2.ToLower()
作用:将字符转换成小写形式,仅对字母有效。返回值是转换后的字符串。
使用:字符串变量或常量.ToLower();
例如:"hh".ToLower();
3.Equals() ※
作用:比较两个字符串是否相同。相同返回真,不相同返回假。
使用:字符串变量或常量.Equals(要比较的字符串变量或常量);
例如:"hh".Equals(name2);
4.Split() ※
作用:分割字符串。返回字符串类型的数组。
使用:字符串变量或常量.Split (用于分割的字符数组或字符常量);
例如:
string[] Txt2 = "憨憨|是|他|不是|我".Split('|','他');
//再次声明个字符串数组用于保存Split函数返回的字符串数组。
char[] Fuhao = new char[] { '|','是','|','他' };
string[] Txt1 = Txt.Split(Fuhao);
5.Substring() ※
作用: 截取字符串。返回截取后的子串。
使用:
**注意:**角标范围为 0~(字符串长度-1)
例如:
name1.Substring(2);
//从角标为2 的位置,截取到最后;
name2.Substring(2,2);
//从角标为2 的位置,截取2 个字符;
6.IndexOf()
作用: 查找某个字符串在字符串中第一次出现的位置。返回该字符串第一个字符所在的索引位置值。如果没有找到,返回-1。
使用: 字符串变量.IndexOf(子字符串变量或常量);
例如:name.IndexOf(“on”);
7.LastIndexOf()
作用:查找某个字符串在字符串中最后一次出现的位置。返回该字符串第一个字符所在的索引位置值。如果没有找到,返回-1。
使用:字符串变量或常量.LastIndexOf(子字符串变量或常量);
例如:name.IndexOf(“on”);
8.StartsWith()
作用:判断是否以…字符串开始。如果是,返回 true;如果不是,返回 false。
使用:字符串变量或常量.StartsWith(子字符串变量或常量);
演示:name.StartsWith(“Mo”);
9.EndsWith()
作用:判断是否以…字符串结束。如果是,返回真;如果不是,返回假。
使用:字符串变量.EndsWith(子字符串变量或常量);
演示:name.EndsWith(“key”);
10.Replace() ※
作用:将字符串中的旧字符串替换成一个新字符串,只要是旧字符串就全都替换。返回新的字符串。
使用:字符串变量或常量.Replace(旧字符串,新字符串);
演示:
string Txt = "憨憨|是|憨憨|不是|我";
Console.WriteLine(Txt.Replace("憨","皮"));
//输出皮皮|是|皮皮|不是|我
11.Contains() ※
作用:判断某个字符串中是否包含指定的字符串。如果包含返回真,否则返回假。
使用:字符串变量或常量.Contains(子字符串变量或常量);
例如:name.Contains(“key”);
12.Trim() ※
作用:只能去掉字符串中前后空格。返回处理后的字符串。
使用:字符串变量或常量.Trim();
例如:
string Txt = " 8 0 8 ";
Console.WriteLine("|" + Txt.Trim() + "|");
//结果是输出字符串"|8 0 8|"
//所以空格只能去掉字符串中除了' '以外任意字符前后的空格。
//若字符串由全空格组成,则会去掉全部字符串
13.TrimEnd()
作用:去掉字符串结束后的空格。返回处理后的字符串。若字符串由全空格组成,则会去掉全部字符串
使用:字符串变量或常量.TrimEnd();
例如:address.TrimEnd();
14.TrimStart()
作用:去掉字符串开始前的空格。返回处理后的字符串。若字符串由全空格组成,则会去掉全部字符串
使用:字符串变量或常量.TrimStart();
例如:address.TrimStart();
15.IsNullOrEmpty()
作用:判断一个字符串是否为 null 或者空。如果为 null 或者空,返回真;否则返回假。
**区别:**null 是不占内存空间的,而空字符串(“”)是占内存空间的。
使用:string.IsNullOrEmpty(字符串变量或常量);
例如:
string Txt1 = null;
string Txt2 = "";
Console.WriteLine("0}\n{1}",string.IsNullOrEmpty(Txt1),string.IsNullOrEmpty(Txt2));
1.字符串是引用类型
字符串的数据是存储在堆空间,在栈空间中则用字符串变量的变量名存储了该数据的引用地址。
2.字符串是不可变的——原数据不变
当你给一个字符串变量重新赋值时,旧值并没有销毁——原数据不变,而是重新开辟一块空间来存储新值,然后字符串变量的变量名储存了新值在堆中的地址。此时该string变量指向了新值。
3.字符串可以看做是是自读的字符数组
可以使用 字符串变量[下标] 的形式读取字符串中指定的字符。也可以使用 for 循环变量依次输出字符。
字符串变量或常量.Length;可以取得字符串字符的个数。
拓展:
- string 是类,有个成员用于储存字符串长度
- 与C不同,比C++更加高级的语言的字符串都不用这种用0结尾的字符数组
- 至于C++ 则是:std::string: 标准中未规定需要\0作为字符串结尾。编译器在实现时既可以在结尾加\0,也可以不加。(因编译器不同)
- 在新的C++标准 C++11 里面规定std::string一定是以’\0’结尾
string变量的缺点:
当需要对一个字符串变量进行多次重新赋值时,在内存中会产生大量的垃圾数据信息。因为旧值并没有销毁——原数据还在原空间且内存没有被释放。
所以当多次重新赋值的频率很高时,执行的效率就会 降低。
StringBuilder 简介
StringBuilder 是一个类,是引用类型,动态对象。在创建了一个 StringBuilder 类型的实例后,可以通过追加、移除、替换或插入字符来修改它。
StringBuilder 类型的变量名会一直储存同一个地址。所以不会改变字符串变量名所指向的那一块内存,也不会产生垃圾数据,所以执行效率远远高于 string 类型的字符串变量。
StringBuilder.Length 属性指示 StringBuilder 对象当前包含的字符数。 如果向 StringBuilder 对象添加字符,则其长度将增加。 如果添加的字符数导致 StringBuilder 对象的长度超过其当前容量,则在原内存的基础上分配新内存,此时该对象的内存翻倍,此时 Capacity 属性的值翻倍,新字符将添加到 StringBuilder 对象,并调整其 Length 属性的大小。
string k = "kkkkkkkkkkkkkkkk";//16个k
StringBuilder Txt = new StringBuilder();
Txt.Append(k);//此时Length为16,Capacity为16。
Txt.Append(k);//此时Length为32,Capacity为32,跟16比翻了2倍,内存是之前的2倍
Txt.Append(k);//此时Length为48,Capacity为64,跟32比翻了2倍,内存是之前的2倍
Console.WriteLine(Txt.Capacity);//结果为64,初始容量为16,同时内存也翻了4倍
StringBuilder 对象的额外内存会动态分配,直到达到 StringBuilder.MaxCapacity 属性定义的值。达到最大容量时,不能为 StringBuilder 对象分配更多的内存,此时尝试添加字符或将其扩展到超出其最大容量时,会引发 ArgumentOutOfRangeException 或 OutOfMemoryException 异常。
StringBuilder 对象的默认容量是16个字符,其默认最大容量为 Int32.MaxValue。 如果调用 StringBuilder() 和 StringBuilder(String) 构造函数,则使用这些默认值。
可以通过以下方式显式定义 StringBuilder 对象的初始容量:
StringBuilder 对象默认容量是16个字符,其默认容量最大值为 Int32.MaxValue。如果分配给构造函数调用中的 StringBuilder 对象的字符串长度超过默认容量或指定容量,则 Capacity 属性设置为用 value 参数指定的字符串长度。
string k = "kkkkkkkkkkkkkkkk";//16个k
StringBuilder Txt = new StringBuilder(k,17);//此时默认容量为17
具体实例化方法和修改默认容量 Capacity 的方法如下
构造函数 | 字符串值 | 默认容量 | 最大默认容量 |
---|---|---|---|
StringBuilder() | String.Empty | 16 | Int32.MaxValue |
StringBuilder(Int32) | String.Empty | 由 capacity 参数定义 | Int32.MaxValue |
StringBuilder(Int32, Int32) | String.Empty | 由 capacity 参数定义 | 由 maxCapacity 参数定义 |
StringBuilder(String) | 由 value 参数定义 | 16或 value。 Length,以较大者为准 | Int32.MaxValue |
StringBuilder(String, Int32) | 由 value 参数定义 | 由 capacity 参数或 value定义的。 Length,以较大者为准。 | Int32.MaxValue |
StringBuilder(String, Int32, Int32, Int32) | 由 value 定义。 Substring(startIndex, length) | 由 capacity 参数或 value定义的。 Length,以较大者为准。 | 由 maxCapacity 参数定义 |
StringBuilder Txt = new StringBuilder(); //创建一个对象。
注意:StringBuilder 依赖 System.Text 命名空间。
往 Txt 中追加数据
Txt.Append(i); //追加数据,此处的 i 可以为多种类型的变量或常量。有点类似 + 运算符在起 “连接” 的作用。
Txt.ToString(); //将 Txt 转成字符串形式。
清空 Txt 中的数据
Txt.Clear(); //将 Txt 清空。
Txt 中的单个字符
可以采用输出 string 中单个字符一样的方法,StringBuilder 类型支持通过数组的形式使用。
注意:Stopwatch 依赖System.Diagnostics 命名空间。
Stopwatch sw = new Stopwatch();//声明一个Stopwatch类的变量
sw.Start(); //计时器开始。
sw.Stop(); //计时器结束。
sw.Elapsed; //开始到结束之间的时长。
效率测试
使用 for 循环分别往 string 和 StringBuilder 中追加9万个信息,统计时长。
思维扩展
使用“秒表计时”来判断代码在时间上的执行效率。在后期需要测试执行效率的时候,都可以使用这个方法。
枚举类型是由基础整数数值类型的 一组 命名常量 定义的值类型。
默认情况下,枚举成员的关联常量值类型为 int ; 它们默认从零开始,并按照定义文本顺序增加一。 您可以显式指定任何其他整数类型作为枚举类型的基础类型。您还可以显式指定关联的常数值,如以下示例所示:
enum ErrorCode : ushort
{
None,//关联的常量值为0
Unknown = 1,//此处可以不用指定为1,因为编译器会自动将前一个枚举成员的关联常量值增加1,结果正好为1
ConnectionLost = 100,
txt,//此处txt关联的常量值为101
OutlierReading = 200
}
1. 定义枚举类型
枚举类型定义在什么地方?枚举定义在 namespace 下,这样在当前的命名空间下,所有的类(class)都可以使用该枚举。
语法:
public enum 枚举名
{
值1,
值2,
值N
}
season a = season.春天;
int b = (int)a;
2. 使用枚举
public enum season
{
春天,//0
夏天,//1
秋天,//2
冬天 //3
}
class Program
{
static void Main(string[] args)
{
season a = season.春天;
int b = (int)a;//结果为0
Console.ReadKey();
}
一般用于游戏开发的游戏状态、RPG游戏的职业等多种方面。
1.什么是结构体?
struct 结构体是一种值类型,通常用于封装一些小型变量数据。
结构体和“对象”有很多类似和一样的地方,可以把结构体当成一个迷你版的对象来使用。
结构还可以包含构造函数、常量、字段、方法、属性、索引器、运算符、事件和嵌套类型,但如果同时需要上述几种成员,则应当考虑改为使用类作为类型。
2.Untiy3D 中的结构体
在Unity3D 中提供了很多结构体类型的数据,这些数据储存的量都小。比如:Vector3(三维向量),Color(颜色),Quaternion(四元数),Ray(射线)等等
1.声明结构体
public struct 结构体名称
{
public 数据类型 变量名;
public 数据类型 变量名;
public 数据类型 变量名;
}
2.使用结构体
Person monkey = new Person();
给结构体赋值:
格式: 结构体变量名.变量名 = 值;
结构体取值:
格式: 结构体变量名.变量名;
[访问修饰符] class 类名
{
类的描述信息;
}
访问修饰符: 用于描述这个类的访问权限,可以不写,因为有默认值;
class: 关键字,用于声明一个类,和之前枚举的enum,结构体的 struct 作
用是一样的。
类的描述信息: 描述这类事物的特征(字段,属性,方法);
至于修饰符的默认值,这个则要看类的位置
如果类,结构,代理,枚举是外置的,那修饰符只有:public 和 internal,默认是 internal——内部 。至于 private 和 protected 是用来修饰类的成员。在外置class前面加private,protected不会通过编译。
如果是内置的,就是作为另一个类型的成员,也称内部类型(inner type),这样的话,修饰符可以是全部可用修饰符,默认是private。
什么是对象?
一个具体的个体,就是一个对象。
对象的语法
类名 对象名 = new 类名();
类名: 描述这个对象的类,可以是我们自己定义的,也可以是系统提供的;
**对象名:**我们要通过这个类创建出来的一个具体的个体的名称;
new: 关键字,实例化的意思,new 类名() 就是实例化一个类的对象,通过
这个类创建出一个具体的对象出来。
public 数据类型 字段名;
public: 访问修饰符;
数据类型: 就是数据类型,比如int,string,float,double等;
字段名: 就是变量名,在面向对象编程的类中,变量就叫字段。
类名 对象名 = new 类名();
对象名.字段名 = 值;
对象名.字段名
什么是访问修饰符?
所有类型和类型成员都具有可访问性级别,该级别可以控制 是否可以从你的程序集或其他程序集中的其他代码中使用它们。
而访问修饰符,又称权限修饰符。作用是在进行声明时指定类型或成员的可访问性。
public 与private
public:公开的。通过对象名.xxx 的形式可以直接访问到。
private:私有的。通过对象名.xxx 的形式访问不到。
演示:定义一个Person 类,用于描述人的基本信息。
字段包含:姓名,年龄,性别。
特别演示:对字段数据的恶意赋值。
public 数据类型 属性名
{
get{return 字段名;}
set{字段名= value;}//可以拓展,比如用if-else语句判断value是否符合要求
//get 和 set 的{}里为用户自定义的代码段。
//可只写其中一种
public 数据类型 属性名
{
get{return 字段名;}
}
public 数据类型 属性名
{
set{字段名= value;}
}
}
数据类型: 和要保护的字段的数据类型一样;
属性名: 和字段名一样,只不过首字母要大写;
get: 当通过属性名取值的时候,会自动调用 get 中的代码;
set: 当通过属性名给字段赋值的时候,会自动调用 set 中的代码;
value: 也是系统关键字,代表赋给属性的值;
什么是命名空间?
命名空间,也叫名称空间,英文名是namespace。
命名空间的作用
对不同的代码文件进行分类管理。
命名空间的作用类似于操作系统中的目录和文件的关系,由于文件(类)很多,不便管理,而且容易重名,于是人们设立若干子目录(命名空间),把文件分别放到不同的子目录中,不同子目录(命名空间)中的文件(类)可以同名。调用文件时应指出文件路径——调用类和函数时应 using 命名空间。
命名空间的语法
定义命名空间:namespace 空间名称{ 类 }
引入命名空间:using 空间名称
什么是方法?
方法就是函数,存在面向对象编程的类中的函数称之为方法,方法的使用语法与函数完全一样。
说到底,这俩一个玩意。
什么是普通方法?
普通方法,就是普通函数。
在类中的作用是对对象的“行为”进行描述。
行为:这个对象能干什么。
普通方法语法
访问修饰符 返回值 方法名(参数列表)
{
方法的具体功能代码;
}
例如:
class Jobs
{
private string name;
private Gender gender;
private Profession profession;
private BornAddress bornAddress;
public void DisplayInformation()
{
Console.WriteLine("我叫{0},性别{1},职业是{2},出生地是{3}", name, gender, profession, bornAddress);
}
public 修饰的普通方法可以使用:对象名.方法名()的形式调用;
private 修饰的普通方法无法通过:对象名.方法名()的形式调用。
什么是构造方法?
首先它是一个方法,然后它具有“构造”的作用,所有称之为构造方法。
简单点说,构造方法可以对实例化出来的对象进行初始化。
构造方法的语法要求
public Jobs( string name, Gender gender, Profession profession, BornAddress bornAddress )
{
this.name = name;
this.gender = gender;
this.profession = profession;
this.bornAddress = bornAddress;
}
①构造方法要用 public 修饰,不能用 private 修饰;
②构造方法没有返回值,且连void 也不能写;
③构造方法的方法名字必须跟类名一样;
④构造方法是可以有重载的,可以再创造一个参数与函数代码为空的重载方法,这样允许开发者多情况操作。
构造方法什么时候被调用?
当我们使用 new 关键字实例化一个对象的时候,会首先执行构造方法。
this 关键字
this 代表当前类的对象。
注意事项
当我们的类中不写构造方法的时候,在代码编译后,系统会自动给它添加一个空构造方法。但是如果我们写了一个构造方法,系统就不会自动添加默认的“空构造方法”。
此时若想要有“空构造方法”就必须再写一个“空构造方法”,形成重载方法。
什么是析构方法?
和构造方法相反,构造方法用于初始化一个对象,析构方法常用清理一个对
象,往往干的是“善后”的事情。
当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。(例如在建立对象时用 new 实例化对象的时候开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
析构方法的语法
~类名 ()
{
析构方法代码体;
}
①析构方法不能有任何参数;
②析构方法无返回值也无访问修饰符;
③析构方法由系统自动调用;
④析构方法可以不写,编译系统会自动生成一个缺省(系统默认)的析构函数。它也不进行任何操作。
⑤析构方法只能有一个,不能重载
对象这种“数据”也是引用类型。
对象对对象的赋值,这个的过程是传递的堆空间中的引用地址,所以两个对象都 指向 了 同一个堆空间地址 ,所以通过两个对象中的任意一个 修改了对象中的数据,两个对象都会同时发生改变的。
例如,加设有个名为 Jobs的类:
Jobs a = new Jobs();
Jobs b;
b = a;//此时传递的是地址,数据在堆空间的地址
一般情况下,开发者会先写一个默认的构造方法,也就是无参、无赋值的构造方法,再根据需求写其它有参构造方法。
而 new 运算符在实例化对象的过程中起到以下作用:
①在内存(堆空间)中开辟了一块空间;
②在开辟出来的这个空间中创建对象数据;
③调用对象的构造方法进行对象的初始化。
在开发游戏时,游戏中的一切都是对象。主角是对象,npc 是对象。
为了创建这些对象,我们需要实现针对不同的对象写出相应的类。在类中规划好
这个对象的基本信息,和对象的功能作用。
然后逐一实例化对象,实现对象与对象之间进行相应的交互。
class 子类名:父类名
{
//特有的类成员,也就是在父类的基础数拓展的类成员,比如字段、方法和属性;
//可写可不写。
}
编写父类的构造方法
先在 Profession 类中创建构造方法,用于初始化父类中的字段。
编写子类的构造方法
演示:在各个子类中编写各自的构造方法,再使用 base 关键字将公共值传给父类。
格式如下:
class xiuxian :Jobs//继承名为Jobs的父类,此类已编写了无参与有参的构造方法
{
private string taskInfo;
public TaskNPC(): base(){ }//无参构造方法的继承
public TaskNPC(string taskInfo, string name, NPCType type)
: base(name, type)
{
this.taskInfo = taskInfo;//子类特有的要用this关键字赋值
}
}
关键字 base,代表父类,将公共值传给父类的构造方法进行初始化。
子类名 对象名 = new 子类名();
备注:在实际开发中,一般情况下只会实例化子类的对象,因为子类才是具体的事物,父类是子类之间的公共数据的抽象化。
子类继承父类的全部成员(字段、属性和方法),意味着在子类中可以访问到父类中部分成员。
①每种成员都可以使用 private 和 public 修饰符进行修饰。
②private 修饰的成员,我们在子类中访问不到,public 修饰的字成员,我们在子类中可以访问到。
③实例化对象后就无需 base 关键字,直接 “对象名.成员” 就可以访问。
成员 | 常用修饰符 | 在子类中的访问格式 |
---|---|---|
字段 | private | base.字段名 |
属性 | public | base.属性名 |
方法 | public | base.方法名 |
构造方法 | public | public 子类名(数据类型 参数名):base.(参数名){} |
例如:
//在子类中的定义
public xiuxian(string name, Gender gender, Profession profession, BornAddress bornAddress)
:base( name, gender, profession, bornAddress)
{//不用写
}
方法名相同
父类:
public virtual 返回值 类方法名()
{
功能代码段;
}
子类进行重写:
public override 返回值 类方法名()
{
功能代码段;
}
例如:
public override void Cry()
{
base.Cry();//使用 base 关键字 调用父类中的该方法
Console.WriteLine("咆哮");
}
六大原则在 面向对象编程 中是作为编程的 “指导思想”和“行动指南” 存在的。
> 六大原则如下:
①单一职责原则;②开闭原则;③里氏转换原则;
④依赖倒置原则;⑤接口隔离原则;⑥迪米特原则(最少知道原则);
父类 变量 = new 子类();
。A1.B = C1;
。is 和 as 两个关键字都可以进行类型转换。
对象 is 目标类;
对象 as 目标类;
is:如果转换成功,返回true,失败返回false;
as:如果转换成功,返回对应的对象,失败返回null。
public abstract void Speak();//不能写{},要带上;
①抽象方法的返回值类型前用关键字 abstract 修饰,且无功能代码段。
②其中抽象方法必须存在于抽象类中。
③不能写 {} ,要带上 ;
④子类继承了抽象类后,一定得对父类的所有抽象方法进行重写。 否则编译器会报错。
前置回顾
<1>面向对象的三个特性:封装,继承,多态。都是我们后期规划代码结构的基本思想。
<2>使用 Unity3D 开发一款游戏,大点的项目可能会有几百个独立的脚本文件,这么多的脚本文件,如果没有一个代码结构框架来管理的话,项目是会开发失败的。
使用抽象类结构实现NPC模块
在游戏中会出现很多种不同用途的 NPC ,这些 NPC 有各自的存在的价值和作用,同时又具备一些共性的东西。在开发 NPC 系统的时候,常常是需要提取共性,抽象成一个父类,然后子类继承该父类,进而实现不同作用的 NPC 子类。
例如:
任务NPC,商贩NPC,铁匠NPC,三种 NPC 的种类。
共有属性:npc 的名字,npc 的类型;
共有方法:都能和玩家交互(交谈任务或闲聊);
抽象类->接口
前提:当 抽象类中所有的方法都是抽象方法 的时候
这个时候可以把这个抽象类用另外一种形式来表现,这种形式叫接口。
语法格式和规范
抽象类名的命名规范:
接口名一般为“IXxxx”,I + 接口名(帕斯卡命名法)
类和接口的名称区别:为且仅为前缀"I"
格式:
返回值 方法名(参数列表);
注意事项:
①接口使用 interface 关键字定义,没有 class 关键字
②接口中不能包含字段,但是可以包含自动属性,不支持常规属性。
③接口中定义的方法全是抽象方法,但不需要用 abstract 修饰。
④接口中的成员不允许添加访问修饰符,默认都是public。
当我们对现在已经存在的类的 继承关系 进行 功能扩展 的时候,就可以使用接口来完成相应的工作。
先定义一个私有的字段,然后在为这个私有字段封装一个公开的属性,在属性中实现get 和set 两个方法,这种方式叫做常规属性。
当我们使用常规属性的时候,可以在 get 和 set 方法中,编写逻辑代码以便对 取值 和 赋值 进行逻辑性的检查。
前提:当属性的 get 和 set 只是完成字段的取值和赋值操作,而不包含
任何附加的逻辑代码的时候。
格式如下:
public 数据类型 属性名 { get; set; }//允许赋值和获取
public 数据类型 属性名 { get; }//只允许获取
public 数据类型 属性名 { set; }//只允许赋值
等同于
public 数据类型 属性名
{
get{return 字段名;}
set{字段名= value;}
}
public 数据类型 属性名
{
get{return 字段名;}
}
public 数据类型 属性名
{
set{字段名= value;}
}
当我们使用自动属性的时候,就不需要再写对应的字段了,C#编译器会自动给
我们的自动属性提供一个对应的字段。这提高了代码的简洁性。
注意:
在接口中使用属性,就要用不加上访问修饰符的自动属性,因为接口的方法和属性都是公共的,没有必要写“public”。
而且接口中没有字段,无法编写常规属性。
数据类型 属性名 { get; set; }//允许赋值和获取
数据类型 属性名 { get; }//只允许获取
数据类型 属性名 { set; }//只允许赋值
//在接口中的属性格式
虚方法: 父类中的个别方法用虚方法实现,然后允许子类在有需要的情况下重写这些虚方法。
抽象类: 父类定义一系列的规范,子类去把父类里面定义的这些规范全部实现。
接口: 是一种功能的扩展,是在原有的类的继承关系以外的新功能的扩展。
static 关键字,用于修饰类,字段,属性,方法,构造方法等。
被static 修饰的类称之为“静态类”;
被static 修饰的成员称之为“静态成员”。
类名.静态字段名
进行访问,通过对象名.静态字段名
的方式是访问不到静态字段的。类名.静态字段名= 新的值
;类名.静态属性名
进行访问;类名.静态方法名
进行访问。public void H1()
{}
public static void N1()
{
H1();//失败
}
<1>在程序开发过程中经常会遇到一些典型的问题,在对这些问题进行处理解决
的过程中,慢慢的整理出来了一套系统的解决方案,这套方案称之为“设计模式”。
<2>在游戏中有很多副本,很多Boss 需要击杀和通关,网上就出现了很多针
对性的副本,Boss 的攻略,通过这些攻略可以很方便的通过这些副本和Boss。
<3>在我们的开发过程中,也会遇到很多针对性的问题,我们就可以学习前人总
结好的各种各样的设计模式,来解决这些编程开发中的问题。
<4>大多数情况下,我们只需要把前人总结好的设计模式学会即可。并不需要自
己去研究去创造新的模式。代表性的有《GoF23 种设计模式》。
<1>在类定义内声明一个静态且私有的这么一个当前类的类型的字段;
private static ClassName instance;
<2>创建私有无参构造方法,保证外部无法实例化这个类;
private ClassName() { }
<3>创建一个静态方法,用于创建此类的唯一对象。
public static ClassName Instance()
{
if (instance == null)
{
instance = new ClassName();//没有则创建一个
}
return instance;//返回地址
}
最后实例化的方法为:
ClassName m1 = ClassName.Instance();
ClassName m2 = ClassName.Instance();
最后结果是m1和m2都存有相同的地址,都指向同一块空间
外部类名.嵌套类名
的方式访问到内部类,然后外部类名.嵌套类名 对象名 = new 外部类名.嵌套类名();
。var p = new { Name = "Monkey", Age = 100 };//定义并初始化这个类的对象内两个string的字段
Object 是类,object 是类型。(类与系统关键字的语法颜色区别)
Object Txt;
鼠标左键移到 Object 双击,按下F12,就可以查看到 Object类eg:int的a赋值给object的b
eg:object的b赋值给int的a
前提:两种类型只有存在继承关系的时候,才可能出现装箱或拆箱操作。
指令格式:
#region 定义的名
......
#endregion
作用:
①优化代码结构,当我们一个脚本文件有500 行+,1000 行+的时候,一个脚本
文件中会出现大量的字段,属性,方法,各种各样的功能的代码。
②如果想要快速的定位某个功能的代码,是很不方便的。这个时候我们可以使用区域指令,进行代码折叠,并显示 定义的名 。
类名 对象名 = new 类名(){属性名 = 值;属性名 = 值};