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

 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 2007-07-25 17:08  紫色阴影  阅读(2417)  评论(15编辑  收藏  举报
我要啦免费统计