1. 请简述值类型与引用类型的区别 Heap与Stack有何区别?
a)值类型与引用类型的区别
a. 值类型将数据保存在其自己的内存分配中,而引用类型包含指向保存真实数据的另一个内存位置的指针。引用类型变量存储在堆(heap)中,而值类型变量存储在栈(stack)中
b.常见的值类型包括整形、浮点型、布尔型等数值型变量;而引用类型则包括字符串、对象
b) Heap与Stack有何区别
a. Stack用于静态内存分配,Heap用于动态内存分配,两者都存储在计算机的RAM中
b. 在Stack中分配的变量直接存储在内存中,访问该内存的速度快,并且在编译程序时处理分配。当一个函数调用另一个函数,而这个函数又调用另一个函数时,所有这些函数的执行都会保持暂停状态,直到最后一个函数返回其值。Stack始终以LIFO顺序保留,最近保留的块始终是下一个要释放的块
c. 在Heap上分配的变量在运行时分配内存,访问此内存稍慢,但Heap大小仅受虚拟内存大小限制。Heap的元素彼此没有依赖关系,随时可以随机访问。可以随时分配一个块并随时释放它
d. 在多线程情况下,每个线程都有自己完全独立的stack,但他们将共享Heap。stack是特定于线程的,Heap是特定于应用程序的
e. stack内存是自动释放的,Heap内存由GC释放
2.C#中所有引用类型的基类是什么
所有的基类都是system.object
3.请简述ArrayList和List<Int>的主要区别
a. List<Int>是个泛型列表,只支持存储int类型的变量,没有装箱、拆箱的过程,同时不会产生运行时错误,使用起来更加安全
b. ArrayList可以存储任何引用类型变量,当存储int这种值类型的变量时,会发生装箱、拆箱的过程,由于其对存储的变狼类型无限制,很有可能发生运行时错误
c.ArrayList已经被弃用,应优先使用List<T>
4.请简述GC(垃圾回收)产生的原因,并描述如何避免
a)GC产生原因
当去创建一个对象时,若堆上的内存空间不足,就会启动GC,去回收堆上那些不再使用的变量空间
b)如何避免
a.使用结构体代替类
b.使用对象池技术
c.在合适的时间强制使用GC,而不是由系统自己决定
d.使用System.Text.StringBuilder,在使用注意,创建StringBuilder对象时要设置StringBuilder的初始大小
e.使用公用的对象(静态成员,常量)
f.尽量较少new的次数
5.请描述Interface与抽象类之间的不同
a. 抽象类不提供完整的抽象,但接口确实提供了完整的抽象
b. 使用Abstract我们不能实现多重继承,但使用Interface可以实现多重继承
c. 不能在接口中声明成员字段
d. 不能创建抽象类的对象,只能在类名的帮助下调用抽象类的方法
e.接口是一系列方法的结合,而absctract是对象实例的抽象
6.下列代码在运行中会发生什么问题?如何避免?
List<int>ls = new List<int>(new int[] { 1, 2, 3, 4, 5 });
foreach (int item in ls)
{
Console.WriteLine(item * item);
ls.Remove(item);
}
由于foreach 是只读的,不能一边遍历一边修改,所以会产生运行时错误,修改:
List<int>ls = new List<int>(new int[] { 1, 2, 3, 4, 5 });
for(intj=0,i=0;j<5;j++)
{
Console.WriteLine(ls[i] * ls[i]);
ls.Remove(ls[i]);
}
7.请简述关键字Sealed用在类声明和函数声明时的作用
Sealed修饰的类为密封类,类声明时可防止其他类继承,修饰方法时,可防止派生类重写此方法
8.请简述private,public,protected,internal的区别
public:成员方法及成员变量对任何类和成员都公开,无限制访问
private:成员方法及成员变量仅对该类公开
protected:成员方法及成员变量对该类和其派生类公开
internal:成员方法及成员变量只能在包含该类的程序集中访问
9.反射的实现原理?
反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等
10.面向对象的3个特征的主要作用的是什么?
面向对象的三个特征为封装继承和多态
封装:把客观对象封装成抽象的类并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏
继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展
多态:允许将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用
11:C#的委托是什么?有何用处?
委托(Delegate)是存有对某个方法的引用的一种引用类型变量,引用可在运行时被改变,类似于 C 或 C++中函数的指针。委托(Delegate)特别用于实现事件和回调方法
12:什么叫动态批处理?跟静态批处理有什么区别?
静态批处理:将静态(不移动)GameObject组合成大型Meshes,并以更快的方式渲染它们。静态批处理允许游戏引擎对任何尺寸的几何图形减少绘制调用,只要它们共享相同的材料,并且不移动。它比动态批处理更加高效但是消耗更多的内存
动态批处理:对于足够小的网格物体,动态批处理会转换它们在CPU上的顶点,将许多相似的顶点组合在一起,并一次性绘制它们。因为动态批处理通过将所有GameObject顶点转换为CPU上的世界坐标空间而工作,所以如果该转换工作比执行绘制调用的开销要小,那么这是一个优势。如果Unity共享相同的材质并满足其他标准,Unity可以自动将GameObjects移动到同一个绘制调用中。动态配料是自动完成的,不需要任何额外的其他设置
13.你使用过的设计模式有哪些? 什么是策略模式和动态代理模式?
我使用过观察者模式
策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式
策略模式的优点
策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
策略模式提供了管理相关的算法族的办法。
策略模式提供了可以替换继承关系的办法。
使用策略模式可以避免使用多重条件转移语句
策略模式的缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量
动态代理模式:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象,代理类是在运行时生成的即使动态代理模式,代理类是在编译时就实现好的即为静态代理。实现动态代理的步骤为:
a.定义一个委托类和公共接口。
b.自己定义一个类(调用处理器类,即实现 InvocationHandler 接口),这个类的目的是指定运行时将生成的代理类需要完成的具体任务(包括Preprocess和Postprocess),即代理类调用任何方法都会经过这个调用处理器类(在本文最后一节对此进行解释)。
c.生成代理对象(当然也会生成代理类),需要为他指定(1)委托对象(2)实现的一系列接口(3)调用处理器类的实例