随笔- 54  文章- 3  评论- 762  阅读- 39万 

今天编程的时候随手写下了大概像这样的代码 :

 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);

其实原理都知道,但写代码的时候不细心,导致随手写下错误的代码,以后要多注意,养成写代码的好习惯。

 posted on   紫色阴影  阅读(2420)  评论(15编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
我要啦免费统计
点击右上角即可分享
微信分享提示