日期:2014-05-19  浏览次数:20731 次

C#的一个限制,估计很多人都没发现过
定义个结构
struct   MyStruct
{
public   string   name;
}

然后用它
System.Collections.ArrayList   myStructs   =   new   ArrayList();
MyStruct   myStruct   =   new   MyStruct();
myStruct.name   =   "11111 ";
myStructs.Add(myStruct);

foreach(MyStruct   my   in   myStructs)
{
my.name   =   "222 ";
}
注意了,上面
my.name   =   "222 ";
这行编译时会说“赋值号左边必须是变量、属性或索引器”——读可以,写不允许。写了这么久,居然今天才知道,不过想不通为什么C#要这么限制。

另,如果写成
for(int   i=0;   i <myStructs.Count;   i++)
{
MyStruct   my   =   (MyStruct)myStructs[i];
my.name   =   "333 ";
}
就没有问题

如果定义成
MyStruct[]   myStructs   =   new   MyStruct[1];
用foreach的话,也是同样的编译错误!

但是的但是:如果定义成class,就没上面的问题~~~~!

总结的说:struct搭配foreach,只读。

哪位能从机制上给解释一下.net为什么要这样做咛?

------解决方案--------------------
这个限制和Struct的按值传递有关,个人认为可能是.NET认为这样会导致用户的误解才限制的。
------解决方案--------------------
楼主,这个问题是你没搞明白什么是装箱什么是拆箱
------解决方案--------------------
你放到myStructs这个里面的myStruct 原来在栈里

经过了myStructs.Add(myStruct); 现在堆里多了一个副本(这个是装箱)

foreach(MyStruct my in myStructs)这个里面的my在栈里,这里的修改怎么可能影响你在堆里的myStruct?

把内存分配看懂了就不会问这样的问题了