41. string、stringBuilder
String不变性,字符序列不可变,对原管理中实例对象赋值,会重新开一个新的实例对象赋值,新开的实例对象会等待被GC。
string拼接要重新开辟空间,因为string原值不会改变,导致GC频繁,性能消耗大。
StringBuilder是字符串可变对象。
StringBuilder是非线程安全,所以性能略好,一般用于单线程。
性能比较 StringBuilder>String
如果要操作少量的数据 =string
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
42. 字典Dictionary的内部实现原理
泛型集合命名空间
using System.Collections.Generic;
任何键都必须是唯一
该类最大的优点就是它查找元素的时间复杂度接近O(1),实际项目中常被用来做一些数据的本地缓存,提升整体效率。
实现原理
哈希算法:将不定长度的二进制数据集给映射到一个较短的二进制长度数据集一个Key通过HashFunc得到HashCode
Hash桶算法:对HashCode进行分段显示,常用方法是对HashCode直接取余
解决碰撞冲突算法(拉链法):分段会导致key对应的桶会相同,拉链法的思想就像对冲突的元素,建立一个单链表,头指针存储到对应的哈希桶位置。反之就是通过确定hash桶位置后,遍历单链表,获取对应的value
43.using的作用
资源:实现了IDisposable接口的类或结构。
using语句确保这些资源能够被适当的释放(Resource.Dispose)
using原理:using(分配资源){ 使用资源 } ——> 释放资源 (隐式)
使用资源(可能会导致异常)会被放进Try块里,释放资源(有无异常)都会放进在finally块
using(分配资源)
{
try{ 使用资源 }
finally{ Resource.Dispose}
}
using指令,using+命名空间(或命名空间一个类型) 在源文件的顶端声明
调用成员方法时也可以不使用using,直接命名空间.类.成员方法
44. Mathf.Round和Mathf.Clamp和Mathf.Lerp含义?
Mathf.Round:四舍五入
Mathf.Clamp:左右限值
Mathf.Lerp:插值
45. 能用foreach遍历访问的对象需要实现接⼝或声明⽅法的类型(C#遍历)
IEnumerable;GetEnumerator
List和Dictionary类型可以用foreach遍历,他们都实现了IEnumerable接口,申明了GetEnumerator方法。
46. 什么是里氏替换原则?(C#多态)
里氏替换原则(Liskov Substitution Principle LSP)⾯向对象设计的基本原则之⼀。
里氏替换原则中说,任何基类可以出现的地⽅,⼦类⼀定可以出现,作⽤⽅便扩展功能能
子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法。
子类中可以增加自己特有的方法。
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
47. 想要在for循环中删除List(或者vector,都行)中的元素时,有可能出现什么问题,如何避免?
当删除遍历节点后面的节点时,会导致List.Count进行变化,删除元素后,当根据i++,遍历到删除的节点会发生异常。
处理方法:可以从后往前遍历元素进行操作,即删除在访问的前面。
48. 概述c#中代理和事件?
代理就是⽤来定义指向⽅法的引⽤。
C#事件本质就是对消息的封装,⽤作对象之间的通信;发送⽅叫事件发送器,接收⽅叫事件接收器;
49. New的实现逻辑
rPoint1 = new RefPoint(1);
在应用程序堆上创建一个引用类型对象的实例,并为它分配内存地址。
自动传递该实例的引用给构造函数(正因如此,在构造函数中才能使用this来访问这个实例)。
调用该类型的构造函数。
返回该实例的引用内存地址,复制给 rPoint1 变量,该rPoint1 引用对象保存的数据是指向在堆上创建该类型的实例地址。
50.请简述关键字Sealed用在类声明和函数声明时的作用
类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。