通过论证:查询字段通常返回引用,该引用可以保证是原来的对象的状态的一部分。分析变量在内存中的变化过程。

由:

“A property method may require additional memory or return a reference to something
that is not actually part of the object’s state, so modifying the returned object has no
effect on the original object; querying a field always returns a reference to an object
that is guaranteed to be part of the original object’s state . Working with a property
that returns a copy can be very confusing to developers, and this characteristic is frequently not documented .“

这段话源自《CLR via C#》第4版中第十章 属性 。

这段话主要意思是:一个属性方法(指的是自动属性的get方法)可能要求额外的内存,另外返回的引用实际上不是对象的状态的一部分(意思是返回的不是对象的成员字段的引用),所以修改返回值不会影响原来的对象;查询字段通常返回引用,该引用可以保证是原来的对象的状态的一部分。属性返回的是copy,这会让开发者感到困惑,而且这种情况通常没有被记载在文档中。

我为了验证这段话中”查询字段通常返回引用,该引用可以保证是原来的对象的状态的一部分“,写了个Demo。

声明一个类型Student,

成员:

3个字段:Int32类型的no、String类型的str、Object类型的obj;

3个查询字段的方法: 返回Int32的方法GetNo()、返回String类型的方法GetStr()、返回Object类型的方法GetObj(

复制代码
class Student
    {
        internal Int32 no = 1;
internal Object obj = new Object();
        internal Int32 GetNo() { return this.no; }
internal Object GetObj() { return this.obj; }
    }
复制代码

在控制台的Main()方法中

复制代码
static void Main(string[] args)
        {
            var s1 = new Student();
            var no = s1.GetNo();//no的地址应该等于s1的成员no的地址
              var obj = s1.GetObj();//obj的地址应该等于s1的成员obj的地址
              Console.WriteLine(ReferenceEquals(no, s1.no));//使用静态ReferenceEquals()方法判断两个变量是否相等,下同。
            Console.WriteLine(ReferenceEquals(obj, s1.obj));
            Console.Read();
        }
复制代码

验证问题:

首先科普一下:

1、当声明一个变量时,立刻就会在栈上面声明该变量(入栈),该变量存储方式应该是一个键值对(key:堆地址;value:变量的值,注意:如果是引用类型的话,这里就是在堆上的地址)。

2、在vs中调试→窗口→即时窗口,通过&+变量名,来观察变量在栈中的情况。例如:

&s1.no                              //观察变量s1的成员no
0x030c499c                       //键:栈上的地址。
    *&s1.no: 1                    //值:1。
&s1.obj                            //观察变量s1的成员obj
0x030c4998                     //键:栈上的地址。
    *&s1.obj: {51136932} //值:在堆上的地址。//如果是*&s1.obj: {0},那么就表示未在堆上开辟空间,值为null。

执行下程序,进行观察,结果如下:

释疑引用地址传递

 

观察的结果完全符合ReferenceEquals()的结果。

那么这个通过方法获取返回值的过程是什么样的呢?我用下图模拟下变量在内存中发生的过程。

图解引用地址传递的过程

那么到这里,也就证明了查询字段获取的返回值,确实是对象状态的一部分。

posted @   蝌蝌  阅读(444)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示