首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
清单首页.net文章详情

金三银四面试:C#.NET面试题中高级篇4,高薪必备

目录

1、什么是闭包?C#实现方法

2、Debug.Write()和Trace.Write()之间有什么区别?二者分别应该用于何处?

3、NET中如何实现深拷贝(deep copy)?

4、如何解决.net中的内存泄漏问题?用到过哪些检测工具?

5、内存泄漏和内存溢出的区别是什么?

6、请简述async函数的编译方式?

7、请简述Task状态机的实现和工作机制?

8、什么是序列化,什么时候会用到序列化

1、什么是闭包?C#实现方法

闭包就是能够读取其他函数内部变量的函数。C#通过Lambda表达式可以访问Lambda表达式块外部的变量,这成为c#闭包。当引用外部变量时,需要注意,外部变量变化时,lambda表达式的结果也可能会随着外部变量变化而变化。如下面的例子:

代码语言:javascript
复制
int y = 5;
Func<int, int> lambda = x => x + y;
Console.WriteLine(lambda(1));
y = 10;
Console.WriteLine(lambda(1));

2、Debug.Write()和Trace.Write()之间有什么区别?二者分别应该用于何处?

Debug.Write是调试的时候向跟踪窗口输出信息。

当编译模式为debug的时候才有效,为release的时候Debug.Write在编译的时候会忽略,而Trace则是在debug和release两种模式下均可以向跟踪窗口输出信息。

3、NET中如何实现深拷贝(deep copy)?

实现IClonable接口

4、如何解决.net中的内存泄漏问题?用到过哪些检测工具?

.NET内存泄漏,更准确的说应该是对象超过生命周期而不能被GC回收。

常见的内存泄露有:

a、静态引用;b、控件不使用后未销毁;c、调用非托管资源而未释放;d、事件注册后未解除注册,等。

解决方案:

(1) Dispose()的使用

  如果使用的对象提供Dispose()方法,那么当你使用完毕或在必要的地方(比如Exception)调用该方法,

特别是对非托管对象,一定要加以调 用,以达到防止泄露的目的。

(2) using的使用

using除了引用Dll的功用外,还可以限制对象的适用范围,当超出这个界限后对象自动释放,比如using语句的用途定义一个范围,将在此范围之外释放一个或多个对象。

(3) 事件的卸载

  这个不是必须的,推荐这样做。之前注册了的事件,关闭画面时应该手动注销,有利于GC回收资源。

(4) API的调用

  一般的使用API了就意味着使用了非托管资源,需要根据情况手动释放所占资源,特别是在处理大对象时。

4.5继承 IDisposable实现自己内存释放接口 Net 如何继承IDisposable接口,实现自己的Dispose()函数

(5)弱引用(WeakReference )

  通常情况下,一个实例如果被其他实例引用了,那么他就不会被GC回收,而弱引用的意思是,如果一个实例没有被其他实例引用(真实引用),

而仅仅是被弱引 用,那么他就会被GC回收。

等等

诊断工具:

a、大多使用windows自带的perfmon.msc,b、用过的工具里面CLRProfiler 和dotTrace还行,windbg也还行。不过坦白的说,准确定位比较费劲,最好还是按常规的该Dispose的加Dispose,也可以加 GC.Collect()

5、内存泄漏和内存溢出的区别是什么?

简单来说,操作系统就像资源分配人员,你要使用内存的时候分给你,你用完了还给它。如果你使用了没有分配给你的内存就是内存溢出,如果你用完了没有了就是内存泄漏。

会引起的问题:

内存溢出存在的问题是你用了没有分配给你的内存,系统是不知道的,他又把内存分配给了其他程序,结果就是别人也写了或者读了这个内存。程序可能崩溃。当然也可能没问题,所以内存溢出往往不好查。

内存泄漏的问题就比理解,你没有还给系统,系统的内存就越来越少。直到没有可用内存。

泄漏是占着不用了,溢出是用不该用的地方;溢出一般会出事,泄漏在内存无限时不会出事。

泄漏是说你的程序有BUG 导致内存不释放。溢出是指内存不够用了 导致不够用的原因很多 泄漏只是其中一种。

6、请简述async函数的编译方式?

async/await是C# 5.0推出的异步代码编程模型,其本质是编译为状态机。只要函数前带上async,就会将函数转换为状态机。

具体在实际编码中怎么用呢?举个例子:

小明早上起床要吃早餐:要刷牙洗脸(2分钟),要冲牛奶(5分钟),要煎鸡蛋(3分钟),然后所有都准备好了,开吃.

如果这个需求以同步的方式进行,总共会花10分钟,才能成功吃到早餐.

但是在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前添加await,因为是同步执行,并等待所有线程执行完成,就可以成功吃到早餐,只需要5分钟.

还有一种情况:在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前不添加await,这样函数里的要干的事情,将不会阻塞,直接2分钟就跳出函数.但是不能成功吃到早餐.因为未添加await,函数结束后,不能保证所有动作都执行完成.

7、请简述Task状态机的实现和工作机制?

CPS全称是Continuation Passing Style,在.NET中,它会自动编译为:

(1)将所有引用的局部变量做成闭包,放到一个隐藏的状态机的类中;

(2)将所有的await展开成一个状态号,有几个await就有几个状态号;

(3)每次执行完一个状态,都重复回调状态机的MoveNext方法,同时指定下一个状态号;

(4)MoveNext方法还需处理线程和异常等问题。

8、什么是序列化,什么时候会用到序列化

  序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

  可以用到序列化的地方:

  a、数据持久化:比如一个电商平台,有数万个用户并发访问的时候会产生数万个session 对象,这个时候内存的压力是很大的。我们可以把session对象序列化到硬盘中,需要时在反序列化,减少内存压力。

  b、网络传输:我们将系统拆分成多个服务之后,服务之间传输对象,不管是何种类型的数据,都必须要转成二进制流来传输,接受方收到后再转为数据对象。

下一篇
举报
领券