看到这个怪怪的标题额,觉得怪怪的。我要讲的一件事情是因为我是常年的cppuser,想当然的把对stl容器的理解加到了c#中。stl里面的vector等容器,push_back后是将元素的拷贝复制到了容器中,我觉得C#应该也是这么做的,实际却不是。我前段时间在做一个unity3d的小minigame时候就碰到了这样的问题。
我写了下面的一个小类来存储玩家的姓名列表,开始我是这么写的。
public class PlayerNames { public int numOfPlayers; public ArrayList nameList = new ArrayList(); public void Write() { numOfPlayers = nameList.Count; PlayerPrefs.SetInt("NumOfPlayers", numOfPlayers); for (int i = 0; i < numOfPlayers; ++i) { PlayerPrefs.SetString(i.ToString() + "playerNames", nameList[i] as string); } } public void Read() { numOfPlayers = PlayerPrefs.GetInt("NumOfPlayers", 0); string name = new string(); for (int i = 0; i < numOfPlayers; ++i) { name = PlayerPrefs.GetString(i.ToString() + "playerNames", "user"); nameList.Add(name); } } };
这段代码的结果是,nameList全部是最后一个玩家的姓名,很明显nameList存储了name的N次引用。对应到cpp中理解就是,nameList存储了name的N个指针。而且循环每次都在修改name的值,所以最终得到的就是N个一样的值咯。很有意思吧。改正的方法也很简单,把name定义在循环内部即可。那么对于c#中的栈对象(值类型),比如int等,会不会有这样的情况了。用下面的小程序测试一下吧。
using System; using System.Collections; namespace Test { class Program { static void Main(string[] args) { int numOfPlayers = 10; ArrayList nameList = new ArrayList(); int nN = 0; for (int i = 0; i < numOfPlayers; ++i) { nN = i; nameList.Add(nN); } for (int i = 0; i < numOfPlayers; ++i) { Console.WriteLine(nameList[i]); } } } }