怕考试的日记本 · openlayers ...· 1 年前 · |
绅士的啤酒 · Nestjs Fastify ...· 1 年前 · |
宽容的毛衣 · logstash同步mysql数据到Elas ...· 1 年前 · |
鬼畜的蚂蚁 · Jmeter接口测试问题整理(一) - 知乎· 1 年前 · |
正直的芹菜 · datetime - How to ...· 1 年前 · |
我知道值类型应该是不可变的,但这只是一个建议,而不是规则,对吧?那么为什么我不能这样做呢:
struct MyStruct
public string Name { get; set; }
public class Program
static void Main(string[] args)
MyStruct[] array = new MyStruct[] { new MyStruct { Name = "1" }, new MyStruct { Name = "2" } };
foreach (var item in array)
item.Name = "3";
//for (int i = 0; i < array.Length; i++)
// array[i].Name = "3";
Console.ReadLine();
}
代码中的foreach循环无法编译,而带注释的for循环运行良好。错误消息:
无法修改“item”的成员,因为它是“foreach迭代变量”
为什么会这样呢?
发布于 2011-04-13 22:27:23
因为foreach使用枚举器,并且枚举器不能更改基础集合,但是 可以 更改集合中的对象引用的任何对象。这就是值和引用类型语义发挥作用的地方。
在引用类型(即类)上,所有集合存储的都是对对象的引用。因此,它实际上从来没有接触过对象的任何成员,并且根本不关心它们。对对象的更改不会影响集合。
另一方面,值类型将其整个结构存储在集合中。如果不更改集合并使枚举数无效,则无法访问其成员。
此外,枚举数返回集合中的值的副本。在ref类型中,这没有任何意义。引用的副本将是相同的引用,您可以以任何想要的方式更改被引用的对象,并将更改扩展到范围之外。另一方面,值类型意味着您得到的只是对象的一个副本,因此对该副本的任何更改都不会传播。
发布于 2011-04-13 22:20:06
这是一个建议,从这个意义上说,没有什么能阻止你违反它,但它确实应该比“这是一个建议”更重要。例如,由于您在这里看到的原因。
值类型将实际值存储在变量中,而不是引用中。这意味着您的数组中有值,并且在
item
中有该值的副本,而不是引用。如果允许更改
item
中的值,则不会反映在数组中的值上,因为它是一个全新的值。这就是为什么它是不被允许的。
如果你想这样做,你必须按索引循环数组,而不是使用临时变量。
发布于 2011-04-13 22:46:25
结构是值类型。
类是引用类型。
ForEach
构造使用
IEnumerator
of
IEnumerable
数据类型元素。当发生这种情况时,变量在某种意义上是只读的,您不能修改它们,并且由于您具有值类型,因此您不能修改所包含的任何值,因为它共享相同的内存。
C#语言规范第8.8.4节:
迭代变量对应于一个只读局部变量,其作用域扩展到嵌入式语句
要修复此问题,请使用结构的类实例;
class MyStruct {
public string Name { get; set; }
鬼畜的蚂蚁 · Jmeter接口测试问题整理(一) - 知乎 1 年前 |