繁体   English   中英

C#基本类型(双精度,整数等)和结构差异

[英]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代替那里的数字。

引用类型是通过引用复制 ; 您没有在存储中获得该值的副本 ,而是得到了可以让您找到该存储的内容

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

现在清楚了吗?

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

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

这是可变结构是邪恶的另一个原因。

您的逻辑有些偏离。

在第一个示例中,您要用全新的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM