开发者

C# Primitive types (double, int, etc) and Struct differences

I am confused with structs.

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.
  }
}

Now why I am able to set the value of the structure a, and not of the structure's field b ? The answer I read is that I have a copy of b and not b's backing field. By the same logic I must have a copy of a, not a, so how it explains that the a property is changed after the permitted assignement

a = 1.0;

? Thank you.

EDIT :

Also in order to still use b inside the A class, "filtered" by the set and get methods and not directly by using the backing field _b, something which could look like this:

MyStruct _b;
MyStruct b { get { r开发者_StackOverflow社区eturn _b; } set { _b=value; } }

and then use the field

_b

, as correctly stated in the answers, I thinked of a silly method to "wrap" the property in an one dimensional array of size 1.

MyStruct[] b { get; set; }

kind of wrapping the struct with a class. I dont know the computational cost of this, but I preferred it from using the field directly inside the A class.

ANSWERED : Ok, the confusion in this question comes, when you are used to interpret properties as fields in your mind. If you interpret properties the correct way -as the MsIL does-, all things settle down. All the answers and comments below, are relevant. (Sorry for the bad English.)


You're doing two different things. Here's an example of doing the same thing in both places:

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

In both of these cases, the assignment operator is calling the "setter" of the property. You can think of it as:

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

As a more complicated example, if you wrote:

a = a + 1.0;

that's equivalent to:

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


Suppose you have an assignment to a member access of the form:

expr.field = value;

The value of a struct instance is, by definition, its value. If you are attempting to mutate the field of a struct then you must be attempting to mutate the storage location that stores the value. That is, you must be attempting to mutate the variable. The field is a variable which is a part of another variable.

Therefore, if expr is a struct type then expr must be a variable.

In your example, expr is not a variable. It's a property, and the result of a property access is a value, not a variable.

That might not be clear. Let's try an analogy.

Imagine you have a piece of paper that represents a value of a struct. The paper has a box on it labelled "c", which contains a number.

When you say "b.c = 2.0;" what that does is goes and finds the storage associated with b, and makes a photocopy of the piece of paper it finds there. You then erase the number on the copy you've been handed and replace it with 2.0. Does that do what you want? Of course not. It doesn't change the value of the piece of paper stored in b at all! Value types are copied by value. Because this doesn't do what you want, it is illegal in C#.

Now suppose you have a piece of paper that represents the value of a class. The paper has a box in it labelled "y" which contains a number.

When you say "x.y = 2.0;" what it does is goes and finds the storage associated with x, and hands you one end of a ribbon. The other end of the ribbon is attached to the piece of paper that is the storage associated with x. You follow the ribbon, find the box labelled y at the other end, and replace the number there with 2.0.

Reference types are copied by reference; you don't get a copy of the value in the storage, you get something that lets you find the storage.

That's the difference between value types and reference types; value types are copied by value, reference types are copied by reference.

Is that now clear?


This error occurs when you try to modify the value.

When you write a = 1.0, you're replacing the value - you're assigning the entire value type to a new value. a = 1.0 is equivalent to b = new MyStruct().

This is yet another reason why mutable structs are evil.


Your logic is a little off.

In your first example, you're replacing a double with a brand new double.

In the second example, you're not replacing the struct with another struct. Instead you're trying to modify some field of the struct.

To do similar things, you would have to do:

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

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜