今天编程的时候随手写下了大概像这样的代码 :
public struct Map { private int _Width; private int _Height; public int Width { get { return _Width; } set { _Width = value; } } public int Height { get { return _Height; } set { _Height = value; } } public Map(int width, int height) { this._Width = width; this._Height = height; } } public class Game { private Map _MyMap = new Map(0,0); public Map MyMap { get { return _MyMap; } set { _MyMap = value; } } public Game(){} public Game(int mapWidth, int mapHeight) { _MyMap = new Map(mapWidth,mapHeight); } } static void Main(string[] args) { Game game = new Game(); game.MyMap.Width = 12; }
然而ctrl+shift+B 却出现错误,build不过。心想这么简单的代码怎么可能有错误呢,开始还以为出现了拼写错误。仔细一看错误指向这一行game.MyMap.Width = 12; 错误提示为“Cannot modify the return value of 'ConsoleApplication1.Program.Game.MyMap' because it is not a variable” 。这时我才意识到由于Map是值类型,在.net中传递参数默认是按值传递,当我使用game.MyMap的时候,生成一个Map的临时对象并返回(这个临时对象是_MyMap的拷贝),然后如果修改这个临时对象的属性,这时就会出错,因为这个临时对象返回以后是会被丢弃的,修改它没有任何意义。
如果把struct改成class,编译就可以通过。因为这时候Map为引用类型,Game类中的_MyMap是一个Map类型的引用,它指向分配在托管堆上的Map对象。当使用game.MyMap的时候,也会返回一个临时对象,它是_MyMap的一个拷贝,它和_MyMap指向同一个对象。如果去修改这个对象的属性,自然是没有问题的。值得注意的是game.MyMap返回的是引用的拷贝,所以要避免写出下面这样的代码,原因已经很清楚了。
Game game = new Game(); Map map = game.MyMap; map = new Map(2,3);
其实原理都知道,但写代码的时候不细心,导致随手写下错误的代码,以后要多注意,养成写代码的好习惯。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?