[英]C# Primitive types (double, int, etc) and Struct differences
我对结构感到困惑。
class A
{
double a { get; set; }
MyStruct b { get; set; }
void Modify()
{
a = 1.0; // This compiles.
b.c = 2.0; // Assuming c is a double. This gives the known error.
}
}
现在为什么我可以设置结构a的值,而不是结构字段b的值? 我得到的答案是我有b的副本,而不是b的后备字段。 按照相同的逻辑,我必须有一个a的副本,而不是a,因此它解释了如何在允许的分配后更改a属性
a = 1.0;
? 谢谢。
编辑:
同样,为了仍在A类中使用b,并通过set和get方法对其进行“过滤”,而不是直接通过使用后备字段_b进行“过滤”,看起来可能像这样:
MyStruct _b;
MyStruct b { get { return _b; } set { _b=value; } }
然后使用该字段
_b
,如答案中正确指出的那样,我想到了一种愚蠢的方法来将属性“包装”为大小为1的一维数组。
MyStruct[] b { get; set; }
用一类包装结构。 我不知道它的计算成本,但我更喜欢直接在A类内部使用字段。
回答:好的,当您习惯将属性解释为思想中的字段时,就会出现此问题的困惑。 如果您以正确的方式解释属性( 如MsIL一样 ),那么所有事情都会解决。 以下所有答案和评论都相关。 (对不起,英语不好。)
您正在做两件事。 这是在两个地方都做相同事情的示例:
a = 1.0;
b = new MyStruct(2.0);
在这两种情况下,赋值运算符都在调用属性的“设置者”。 您可以将其视为:
this.SetA(1.0);
this.SetB(new MyStruct(2.0));
作为更复杂的示例,如果您写了:
a = a + 1.0;
等同于:
this.SetA(1.0 + this.GetA());
假设您为以下形式的成员访问分配了权限:
expr.field = value;
根据定义,结构实例的值是其值 。 如果尝试使结构的字段发生突变,则必须尝试使存储该值的存储位置发生变化。 也就是说,您必须尝试对变量进行突变。 该字段是一个变量,它是另一个变量的一部分 。
因此,如果expr为结构类型,则expr必须为变量 。
在您的示例中,expr不是变量。 它是一个属性,属性访问的结果是一个值 ,而不是变量 。
这可能不清楚。 让我们尝试一个类比。
假设您有一张纸代表一个结构的值。 纸张上有一个标有“ c”的框,其中包含一个数字。
当您说“ bc = 2.0;”时 所要做的就是找到与b相关的存储,并对其找到的纸张进行复印。 然后,您将已删除的副本上的号码删除,并用2.0代替。 那可以做什么? 当然不是。 它根本不会改变存储在b中的那张纸的价值! 值类型按value复制 。 因为这不能满足您的要求,所以在C#中是非法的。
现在假设您有一张纸代表了一个类的价值。 纸张上有一个标有“ y”的框,其中包含一个数字。
当您说“ xy = 2.0;”时 它要做的是找到与x关联的存储,然后将您交给功能区的一端。 色带的另一端连接到与x关联的存储纸上。 跟随功能区,找到另一端标记为y的框,然后用2.0代替那里的数字。
引用类型是通过引用复制的 ; 您没有在存储中获得该值的副本 ,而是得到了可以让您找到该存储的内容 。
这就是值类型和引用类型之间的区别; 值类型按值复制,引用类型按引用复制。
现在清楚了吗?
您的逻辑有些偏离。
在第一个示例中,您要用全新的double替换double。
在第二个示例中,您没有用另一个结构替换该结构。 相反,您尝试修改该结构的某些字段。
要执行类似的操作,您将必须执行以下操作:
a = 10.1;
b = new MyStruct(10.1);
a = 11.1;
b = new MyStruct(11.1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.