C#原始类型(double,int等)和Struct差异

时间:2011-01-19 14:17:12

标签: c# properties struct field primitive

我对结构感到困惑。

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那样 - 所有事情都会解决。以下所有答案和评论都是相关的。 (抱歉英语不好。)

4 个答案:

答案 0 :(得分:5)

你做了两件不同的事情。以下是在两个地方执行相同事情的示例:

a = 1.0;
b = new MyStruct(2.0);

在这两种情况下,赋值运算符都在调用属性的“setter”。您可以将其视为:

this.SetA(1.0);
this.SetB(new MyStruct(2.0));

作为一个更复杂的例子,如果你写了:

a = a + 1.0;

相当于:

this.SetA(1.0 + this.GetA());

答案 1 :(得分:4)

假设您对表单的成员访问权限进行了分配:

expr.field = value;

根据定义,struct实例的值是其值。如果您试图改变结构的字段,那么您必须尝试改变存储存储位置。也就是说,您必须尝试改变变量。该字段是一个变量,它是另一个变量的部分

因此,如果expr是结构类型,则 expr必须是变量

在您的示例中,expr不是变量。它是一个属性,属性访问的结果是,而不是变量

这可能不太清楚。我们来试试吧。

想象一下,你有一张纸代表了一个结构的价值。该纸上有一个标有“c”的方框,其中包含一个数字。

当你说“b.c = 2.0;”时它的作用是找到与b相关的存储,并制作它在那里找到的那​​张纸的复印件。然后删除您已经交出的副本上的数字,并将其替换为2.0。这样做你想要的吗?当然不是。它根本不会改变存储在b中的纸张的价值!值类型按值复制。因为这不符合你的要求,所以在C#中是违法的。

现在假设你有一张纸代表了一个类的价值。该报纸上有一个标有“y”的方框,其中包含一个数字。

当你说“x.y = 2.0;”时它的作用是找到与x相关的存储空间,并将你的一端带到一个功能区。色带的另一端连接到与x相关的存储器的纸张上。您按照功能区,在另一端找到标记为y的框,并将其替换为2.0。

引用类型通过引用复制 ;如果您没有获得存储中值的副本,则可以使用来查找存储

这是值类型和引用类型之间的区别;值类型按值复制,引用类型通过引用复制。

现在清楚了吗?

答案 2 :(得分:1)

尝试修改值时会发生此错误。

当您编写a = 1.0时,您替换值 - 您将整个值类型分配给新值。 a = 1.0相当于b = new MyStruct()

这是mutable structs are evil

的另一个原因

答案 3 :(得分:1)

你的逻辑有点偏。

在你的第一个例子中,你用一个全新的双人替换双人。

在第二个示例中,您不是要用另一个结构替换该结构。相反,你正在尝试修改结构的某些字段。

要做类似的事情,你必须这样做:

a = 10.1;
b = new MyStruct(10.1);

a = 11.1;
b = new MyStruct(11.1);