目录
2、Debug.Write()和Trace.Write()之间有什么区别?二者分别应该用于何处?
5、内存泄漏和内存溢出的区别是什么?
闭包就是能够读取其他函数内部变量的函数。C#通过Lambda表达式可以访问Lambda表达式块外部的变量,这成为c#闭包。当引用外部变量时,需要注意,外部变量变化时,lambda表达式的结果也可能会随着外部变量变化而变化。如下面的例子:
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两种模式下均可以向跟踪窗口输出信息。
实现IClonable接口
.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 导致内存不释放。溢出是指内存不够用了 导致不够用的原因很多 泄漏只是其中一种。
async/await是C# 5.0推出的异步代码编程模型,其本质是编译为状态机。只要函数前带上async,就会将函数转换为状态机。
具体在实际编码中怎么用呢?举个例子:
小明早上起床要吃早餐:要刷牙洗脸(2分钟),要冲牛奶(5分钟),要煎鸡蛋(3分钟),然后所有都准备好了,开吃.
如果这个需求以同步的方式进行,总共会花10分钟,才能成功吃到早餐.
但是在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前添加await,因为是同步执行,并等待所有线程执行完成,就可以成功吃到早餐,只需要5分钟.
还有一种情况:在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前不添加await,这样函数里的要干的事情,将不会阻塞,直接2分钟就跳出函数.但是不能成功吃到早餐.因为未添加await,函数结束后,不能保证所有动作都执行完成.
CPS全称是Continuation Passing Style,在.NET中,它会自动编译为:
(1)将所有引用的局部变量做成闭包,放到一个隐藏的状态机的类中;
(2)将所有的await展开成一个状态号,有几个await就有几个状态号;
(3)每次执行完一个状态,都重复回调状态机的MoveNext方法,同时指定下一个状态号;
(4)MoveNext方法还需处理线程和异常等问题。
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
可以用到序列化的地方:
a、数据持久化:比如一个电商平台,有数万个用户并发访问的时候会产生数万个session 对象,这个时候内存的压力是很大的。我们可以把session对象序列化到硬盘中,需要时在反序列化,减少内存压力。
b、网络传输:我们将系统拆分成多个服务之后,服务之间传输对象,不管是何种类型的数据,都必须要转成二进制流来传输,接受方收到后再转为数据对象。