考虑Foo结构如下:
struct Foo
{
public float X;
public float Y;
public Foo(float x, float y)
{
this.X = x;
this.Y = y;
}
public void Change(float x)
{
this.X = x;
}
}
Run Code Online (Sandbox Code Playgroud)
我理解修改构造函数中的字段,这对我和我理解结构作为值,类似数字的不可变类型是完全合乎逻辑的.
然而,因为可以T"做:
Foo bar = new Foo(1, 2);
bar.X = 5;
Run Code Online (Sandbox Code Playgroud)
为什么可以使用:
Foo bar = new Foo(1, 2);
bar.Change(5);
Run Code Online (Sandbox Code Playgroud)
编辑:如果结构是可变的,那么为什么它们不能在列表中修改或从属性返回?
Eri*_*ert 11
既然一个人做不到
Foo bar = new Foo(1, 2);
bar.X = 5;
Run Code Online (Sandbox Code Playgroud)
为什么可以使用:
Foo bar = new Foo(1, 2);
bar.Change(5);
Run Code Online (Sandbox Code Playgroud)
您的原始问题实际上无法回答,因为它是基于一个完全错误的假设.这两个代码示例都是完全合法的,因此关于为什么一个是非法的问题是荒谬的.让我们继续你的后续问题:
如果结构是可变的,那么为什么在列表中或从属性返回时它们不能被修改?
因为变量是可变的,值是不可变的.
这就是为什么他们被称为"变量",毕竟,因为他们可以改变.
当你说"bar.X = 5"时,"bar"是一个局部变量.变量可以更改.
当你说"bar.Change(5)"时,"bar"是一个局部变量.变量可以更改.
当你说"myArray [123] .X = 5"时,"myArray [123]"是一个数组元素,数组元素是一个变量.变量可以更改.
当你说"myDictionary [123] .X = 5"时,"myDictionary [123]" 不是变量.该值从字典返回,而不是对存储位置的引用.由于这是一个值,而不是一个变量,因此没有任何东西可以改变,所以编译器不允许它改变.
一个微妙的问题是,当您尝试更改字段时,接收方必须是变量.如果它不是变量,那就毫无意义; 你显然是在试图改变一个变量而且没有什么可以变异的.当你调用一个方法时,接收者必须是一个变量但是如果你有一个值呢?该方法可能不会尝试改变任何东西,因此应该允许成功.如果方法的接收者在结构上调用不是变量,编译器实际上做了什么,然后它创建一个新的临时局部变量并使用该变量调用该方法.所以如果你说:"myDictionary [123] .Change(5);" 这跟说的一样
var temp = myDictionary[123];
temp.Change(5);
Run Code Online (Sandbox Code Playgroud)
这里"temp"是一个变量,允许变异方法改变临时副本.
那现在清楚了吗?这里的关键点是变量可以改变.