请简述ArrayList和List的主要区别?
ArrayList存在不安全类型(ArrayList会把所有插入其中的数据都当做Object来处理)装箱拆箱的操作。
List是泛型,可以指定特定的类型,避免过多的装箱拆箱操作,增加对内存的消耗。
简述一下对象池,你觉得在FPS里哪些东西适合使用对象池?
对象池(ObjectPool)就存放需要被反复调用资源的一个空间。
当一个对象会大量生成的时候,如果每次都销毁,创建会很费时间,通过对象池把暂时不用的对象放到一个池中(也就是一个集合),当下次要重新生成这个对象的时候先去池中查找一下是否有可用的对象,如果有的话就直接拿出来使用,不需要再创建,如果池中没有可用的对象,才需要重新创建,利用空间换时间来达到游戏的高速运行效果。
在FPS游戏中常被大量复制的对象包括:子弹,敌人,粒子等。
什么叫做链条关节?
链条关节(Hinge Joint),可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力,但是达到固定距离后就会产生拉力。
结构体和类有何区别?
结构体是一种值类型,而类是引用类型。
值类型、引用类型是根据数据存储的角度来分的。(值类型用于存储数据的值,引用类型用于存储对实际数据的引用)
结构体就当成值来使用的,类则通过引用来对实际数据操作。
ref参数和out参数是什么?有什么区别?
ref和out参数的效果一样,都是通过关键字找到定义在主函数里面的变量的内存地址,并通过方法体内的语法改变它的大小。
不同点就是输出参数必须对参数进行初始化。(ref必须初始化,out参数必须在函数里赋值。)
ref参数是引用,out参数为输出参数。
C#的委托是什么?有何用处?
delegate委托类似于一种安全的指针引用,在使用它时是当做类来看待而不是一个方法,相当于对一组方法的列表的引用。
用处:用委托使得程序员可以将方法引用封装到委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。
委托是面向对象的,而且是类型安全的。
C#中四种访问修饰符是哪些?各有什么区别?
C#中有四种访问修饰符:public、private、protected、internal;
public:存取不受限制;
private:只有包含该成员的类可以存取;
protected:只有包含该成员的类以及派生类可以存取;
internal:只有当前工程可以存取;
请描述Interface与抽象类之间的不同?
1、一个类只能继承一个抽象类,但可以同时继承多个接口;
2、抽象类里面可以有字段,接口里面不能有字段;
3、抽象类里面可以有private私有成员,接口里面所有的成员都是public公有的;
4、抽象类的成员可以带或者不带访问修饰符,接口里面一定不带访问修饰符;
5、一个子类继承抽象类时需重写里面的抽象方法,当子类是抽象类时可以不用重写;而继承接口时一定要实现接口里面的成员;
向量的点乘,叉乘及归一化的意义?
1、点乘描述了两个向量的相似程度,结果越大两向量越相似,还可表示投影;
2、叉乘得到的向量垂直于原来的两个向量;
3、标准化向量:用在只关心方向,不关心大小的时候;
简述StringBuilder和String的区别?
String是字符串常量。
StringBuffer是字符串变量,线程安全;
StringBuilder是字符串变量,线程不安全。
String类型是个不可变的对象,当每次对String进行改变时都需要生成一个新的String对象,然后将指针指向一个新的对象,如果在一个循环里面,不断的改变一个对象,就要不断用String类型;
StringBuilder对象在做字符串连接操作时是在原来的字符串上进行修改,改善了性能。
连接操作频繁的时候,使用StringBuilder对象。(建议在不断更改对象的地方不要使用String)
值类型和引用类型有何区别?
1、值类型的数据存储在内存的栈中;引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地主;
2、值类型存取速度快;引用类型存取速度慢;
3、值类型表示实际数据;引用类型表示指向存储在内存堆中的数据的指针或引用;
4、值类型继承自System.ValueType;引用类型继承自System.Object;
5、栈的内存分配是自动释放;而堆在.NET中会有GC来释放;
6、值类型的变量直接存放实际的数据;而引用类型的变量存放的则是数据的地址,即对象的引用;
在类的构造函数前加上static会报什么错?为什么?
构造函数格式为public+类名,如果加上static会报错(静态构造函数不能有访问修饰符)。
如果什么修饰符都不加的话不会报错,静态构造函数一般是起初始化作用。
原因:静态构造函数不允许访问修饰符,也不接受任何参数;无论创建多少类型的对象,静态构造函数只执行一次;
运行库创建类实例或者首次静态成员之前,运行库调用静态构造函数;
静态构造函数执行先于任何实例级别的构造函数;
显然也就无法使用this和base来调用构造函数;
List(链表)和Array(数组)的区别在哪里?
1、从逻辑结构来看:
A、Array数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;Array数组可以根据下标直接存取。
B、List链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(Array数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)
2、从内存存储来看:
A、(静态)Array数组从堆中分配空间,对于程序员方便快速,但是自由度小。
B、List链表从堆中分配空间,自由度大但是申请管理比较麻烦。
可以看出:如果需要快速访问数据,很少或不插入和删除元素,就应该用Array数组;如果需要经常插入和删除元素就需要用List链表数据结构。
请简述GC(垃圾回收)产生的原因,并描述如何避免?
当用new创建一个对象时,当可分配的内存不足,GC就会去回收未使用的对象,但是GC的操作是非常复杂的,会占用很多CPU时间,对于移动设备来:频繁的垃圾回收会严重影响性能。
建议可以避免GC频繁操作
--1、减少用new创建对象的次数,在创建对象时会产生内存碎片;
--2、使用公用的对象(静态成员,常量),但是不能乱用,因为静态成员和常量的生命周期是整个应用程序;
--3、在拼接大量字符串时使用StringBuilder。
--4、使用Object Pool(对象池)技术;
C#函数Func(string a, string b)用Lambda表达式怎么写?
(a, b)=>{}
请说出面向对象的设计原则,并分别简述它们的含义?
6种设计原则:单一职责原则、开放封闭原则;里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则;
单一职责原则:一个类,最好只做一件事,只有一个引起它的变化;
开放封闭原则:对于扩展是开放的,对于更改是封闭的;
里氏替换原则:子类必须能够替换其基类;
依赖倒置原则:依赖于抽象;
接口隔离原则:使用多个小的专门的接口,而不要使用一个大的总接口;
迪米特法则:如果两个类不必彼此通信,那么这两个类就不应当发生直接的相互作用;
反射的实现原理? 审查元数据并收集关于它的类型信息的能力?
反射实现原理:在运行时根据程序集及其中的类型得到元数据。
反射的射线步骤:1、导入using System.Reflection;
步骤2:Assembly.Load(“程序集”); :加载程序集,返回类型是一个Assembly;
步骤3:得到程序集中所有类的名称:
foreach(Type type in assembly.GetTypes()){
string t = type.Name;
}
步骤4:获取当前类的类型:
Type type = assembly.GetType(“程序集.类型”);
步骤5:创建此类型实例:
Activator.CreateInstance(type);
步骤6:获取当前方法:
MethodInfo mInfo = type.GetMethod(“方法名”);
步骤7:调用:
mInfo.Invoke(null, 方法参数);
类和结构体的区别?
1、类是引用类型;结构体是值类型;
2、结构体和类初始化都使用了new,但一个是分配在堆上,一个在栈上;
3、结构体是隐式的sealed,不能被继承,也不能从另一个类或结构体继承;类可以继承;
建议:当处理数量小的场合使用结构体比较好;对于大量的逻辑对象,使用类比较好;
常用Mathf类函数?
【Mathf.Abs()】:绝对值(static float Abs(float f);)
【Mathf.Ceil()】:上限值(static float Ceil(float f);)
【Mathf.Clamp()】:限制(static float Clamp(float value, float min, float max);)
【Mathf.Lerp()】:插值(static float Lerp(float from, float to, float t);)
【Mathf.Max()】:最大值(static float Max(params float[] values);)
【Mathf.Round()】:四舍五入(static float Round(float f);)
【Mathf.PI】:圆周率(static float PI;)
C#中四种访问修饰符是哪些? 各有什么区别?
C#中的四种访问修饰符:属性修饰符、存取修饰符、类修饰符、成员修饰符;
#A、属性修饰符
Serializable
按值将对象封送到远程服务器;
STAThread
单线程套间的意思,是一种线程模型;
MATAThread
多线程套间的意思,是一种线程模型;
#B、存取修饰符
public
存取不受限制;
private
只有包含该成员的类可以存取;
internal
只有当前工程可以存取;
protected
只有包含该成员的类以及派生类可以存取;
#C、类修饰符
abstract
抽象类:指示一个类只能作为其他类的基类;
sealed
密封类:指示一个类不能被继承;
#D、成员修饰符
abstract
指示该方法或属性没有实现;
sealed
密封方法。可以防止在派生类中对该方法的override(重载);
delegate
委托。用来定义一个函数指针;
const
指定该成员的值只读不允许修改;
event
声明一个事件
extern
指示方法在外部实现;
override
重写。对由基类继承成员的新实现;
readonly
指示一个域只能在声明时以及相同类的内部被赋值;
static
指示一个成员属于类型本身,而不是属于特定的对象;
virtual
指示一个方法或存取器的实现可以在继承类中被覆盖;
new
在派生类中隐藏指定的基类成员,从而实现重写的功能;
游戏对象B是游戏对象A的子物体,游戏对象A经过了旋转,请写出游戏对象B围绕自身的Y轴进行旋转的脚本语句,以及游戏对象B围绕世界坐标的Y轴旋转的脚本语句?
绕世界坐标Y旋转:transform.Rotate(transform.up * speed * Time.deltaTime);
绕自身Y轴旋转:transform.Rotate(Vector3.up * speed * Time.deltaTime);
override和overload的区别?
overload:重载,表示重写父类的函数,但是它只要函数名相同就行,其他的可以不同;
override:重写,是重写父类里的函数,而且方法名、返回类型、参数类型和参数个数都要和父类一致;
const和readonly有什么区别?
1、const关键字:用来声明编译时的常量;
readonly关键字:用来声明运行时的常量;
2、const字段只能在该字段的声明中初始化;而readonly字段可以在声明或在构造函数中初始化。(根据所使用的构造函数,readonly字段可能具有不同的值)
3、const对于引用类型的常数,可能的值只能是string和null;而readonly可以是任何类型;
接口和抽象类的区别是什么?
接口中所有的方法都不能有实现,并且不能指定方法的修饰符;
抽象类中可以有方法的实现,也可以指定方法的访问修饰符;
第一个继承接口的类必须实现接口里的所有方法;
抽象类中抽象方法的实现是由第一个非抽象的派生类来实现;
C#中List、HashTable、Dictionary的区别?
List:是对数组的封装,当List对象的Item元素数量超过了Capacity的数量时,List对象会重新申请一块大小是原来Capacity的两倍的内存空间,然后将当前所有item元素以及待添加元素复制到新的内存空间中,因此频繁的添加数据消耗大,但查询速度快;它的内存区域是连续的,可以用角标来取值;
HashTable、Dictionary:它们的内存是用key值根据hash算法算出来的,它们的内存区域是不连续的,所以在遍历的时候难免会对内存进行换页操作,这样遍历的时间就长;
--Dictionary:1、类型安全,对值类型没有装箱拆箱操作;2、在单条数据的读取上速度快;3、数据的存放是有序的;
--HashTable:线程安全,适合多线程,无序