本文向您展示了如何验证固定关键词的效果。内容简洁易懂,一定会让你眼前一亮。希望通过这篇文章的详细介绍,你能有所收获。
以前讲String join操作的性能时,会涉及到不安全的操作,不安全的操作必然会涉及到指针,于是就产生了fixed关键字。fixed关键字用于固定一个引用地址,因为我们知道CLR的垃圾收集器会改变一些对象的地址,所以改变地址后,对那些对象的引用也会相应改变。这种变化对程序员来说是无意识的,所以在指针操作中是不允许的。否则GC后找不到需要的对象,因为之前已经预留了地址。现在让我们做一个小实验来验证固定关键词的效果。
当然这个实验很简单,可能会让你笑。让我们先准备一堂SomeClass课:
public class some class { public intfield;}然后准备一段代码:
privatedstatunsafetycoutofxedblock(){ vara=new int[100];varc=NewSomeClass();固定(int * ptr=c . Field){ print address(' before GC ',(int)ptr);}GC。收集(2);固定(int * ptr=c . Field){ print address(' after GC ',(int)ptr);} } PrivateStaticVirtuprintAddress(string name,in address){ Console。Write(名称“:0 x”);控制台。写线(地址。ToString(' X ');}在GCOutOfFixedBlock方法中,我们首先分配一个长度为100的int数组,然后创建一个新的SomeClass对象。新数组的目的是创建“垃圾”,目的是在调用GC时改变SomeClass对象在堆中的位置。收集方法。由于垃圾收集发生在固定代码块之外,因此我们在之前和之后打印出的值是不同的:
GC:0x1A058C0之前
GC:后0x1975DF4
值得注意的是,这段代码必须在Release模式下编译,这样CLR才能优化代码的执行,这样CLR在垃圾收集的时候就会发现A数组是垃圾(因为后面的代码不会用到),所以会被回收——或者看不到地址变化的效果。所以,让我们重写一段代码:
privatedstatunsafetycinsidexedblock(){ vara=new int[100];varc=NewSomeClass();
fixed (int* ptr = &c.Field) { PrintAddress("Before GC", (int)ptr); GC.Collect(2); } fixed (int* ptr = &c.Field) { PrintAddress("After GC", (int)ptr); } }
结果如下:
Before GC: 0x1B558C0
After GC: 0x1B558C0
由于GC发生在fixed代码块内部,因此c对象被pin在堆上了,于是GC前后c对象的地址没变,这就是fixed的作用。那么,下面这段代码运行结果是什么呢?
private static unsafe void Mixed() { var a = new int[100]; var c1 = new SomeClass(); var c2 = new SomeClass(); fixed (int* ptr1 = &c1.Field) { PrintAddress("Before GC", (int)ptr1); } fixed (int* ptr2 = &c2.Field) { PrintAddress("Before GC (fixed)", (int)ptr2); GC.Collect(2); } fixed (int* ptr1 = &c1.Field) { PrintAddress("After GC", (int)ptr1); } fixed (int* ptr2 = &c2.Field) { PrintAddress("After GC (fixed)", (int)ptr2); } }
上述内容就是如何验证fixed关键字效果,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/152044.html