(3)使用disposing来判断是.NET的终结器回收还是手动调用Dispose回收,终结器回收不再需要关心释放托管内存;
(4)使用GC.SuppressFinalize(this)来避免多次调用Dispose;
至于本题为什么要关心非sealed类,因为sealed类不用关心继承,因此protected virtual可以不需要。
在子类继承于这类、且有更多不同的资源需要管理时,实现方法如下:
class DerivedClass : BaseClass
{
private bool disposed = false;
protected override void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
// free managed resources...
}
// free unmanaged resources...
base.Dispose(disposing);
}
}
注意:
(1)继承类也需要定义一个新的、不同的disposed值,不能和老的disposed共用;
(2)其它判断、释放顺序和基类完全一样;
(3)在继承类释放完后,调用base.Dispose(disposing)来释放父类。
19. delegate 和 event 本质是什么?请简述他们的实现机制
delegate和event本质都是多播委托(MultipleDelegate),它用数组的形式包装了多个Delegate,Delegate类和C中函数指针有点像,但它们都会保留类型、都保留this,因此都是类型安全的。
delegate(委托)在定义时,会自动创建一个继承于MultipleDelegate的类型,其构造函数为ctor(object o, IntPtr f),第一个参数是this值,第二个参数是函数指针,也就是说在委托赋值时,自动创建了一个MultipleDelegate的子类。
委托在调用()时,编译器会翻译为.Invoke()。
注意:delegate本身创建的类,也是继承于MultipleDelegate而非Delegate,因此它也能和事件一样,可以指定多个响应:
string text = "Hello World"; Action v = () => Console.WriteLine(text); v += () => Console.WriteLine(text.Length); v(); // Hello World // 11
注意,+=运算符会被编译器会翻译为Delegate.Combine(),同样地-=运算符会翻译为Delegate.Remove()。
事件是一种由编译器生成的特殊多播委托,其编译器生成的默认(可自定义)代码,与委托生成的MultipleDelegate相比,事件确保了+=和-=运算符的线程安全,还确保了null的时候可以被赋值(而已)。
总结
这些技术平时可能比较冷门,全部能回答正确也并不意味着会有多有用,可能很难有机会用上。
但如果是在开发像 ASP.NET Core 那样的超高性能网络服务器、中间件,或者 Unity 3D 那样的高性能游戏引擎、或者做一些高性能实时 ETL 之类的,就能依靠这些知识,做出比肩甚至超过 C / C++ 的性能,同时还能享受 C# / .NET 便利性的产品。
群里有人戏称面试时出这些题的公司,要么是心太大,要么至少得开 60k ,因此本文取名为 60k大佬 。
轻松一刻——我的私房.NET后端6k面试题:










