Structures are known to be significant types, and therefore are passed by value. And this becomes a problem when you want to use ready-made structures as fields or class properties. It becomes impossible to work with them, so when you try to change some fields in the structure (which is a property or field), the compiler shouts an error.

In principle, nothing surprising, this is the expected behavior, a copy of the structure is sent to the calling code and the compiler makes it clear that you change the copy, but this will not affect anything. This is understandable, but how to be?

I will give an example:

class Hero { // Структура-поле public Point Coordinates; public Hero { Coordinates = new Point(0,0); } } 

In this case, it will not be possible to change Coordinates.X from external code. What is the practice of working with structures as fields / properties? In the above example, how to change the structure?

  • Why change it from external code? - Grundy
  • @Grundy Well, there can be a lot of examples, for example, in the case that I described, let's say we need to change the coordinates of the hero. Or even more banal, we have a field of type Color, we want to change the color of something there. - Yes Man
  • one
    It all depends on a specific example, as @VladD said in his answer, the example from the question should work in the expected way - Grundy
  • We are waiting for return by ref ... But they will not do it ... - Qwertiy
  • @Qwertiy: It seems to work the same . - VladD

2 answers 2

To begin with, for fields of significant types, you work with the field itself, so this should work as expected:

 Hero hero = new Hero(); hero.Coordinates.X = 100; 

But it is more correct to set the property instead of the field, and there you already work with the copy:

 class Hero { public Point Coordinates { get; set; } public Hero() { Coordinates = new Point(0,0); } } 

In this case, it makes sense to assign the entire value:

 Hero hero = new Hero(); hero.Coordinates = new Point(100, 0); 
  • 3
    or not to forward it at all and work with it only inside the class :) - Grundy
  • 2
    @Grundy: Well, if this is a UI object, then its coordinates usually need to be set outside, so this is a valid user interface. - VladD
  • @VladD "For starters, for the fields of significant types, you work with the field itself, so this should work in the expected way" is there any explanation for why this is happening? Why when through a property, it is passed by value, and through a field, then by reference? - Yes Man
  • @YesMan: The field is not "passed by reference." You simply work with the field itself , lvalue in C ++ terms. But the getter property is an ordinary function, which means, like any function, it always returns a copy of the value for significant types (and a copy of the link for reference types). - VladD pm

Structures are usually needed in order to be able to perform a single operation, such as comparisons or assignments, on a group of data, including heterogeneous ones. I do not want to say that the structures need to be written off into the archive, it's just that many tasks that were solved and solved with the help of structures in other languages, in C #, full-fledged classes are more successfully solved.

In the source code of the System.Windows.Forms.Control class, you can look at the implementation of the Size property, as an example of how Microsoft uses structures.

The control has fields width and height . The Width and Height properties of the same name and the Size property, which returns the width and height values ​​as a single structure of type System.Drawing.Size . For resizing, you have two whole paths: set the width and height separately through the corresponding properties, or set both sizes at once using the Size structure, for example, copied from another control.

If we consider the Location property, then we cannot find separate properties for X and Y, they simply do not exist, although inside the separate fields x and y are used to store the coordinates. In principle, it was possible to use the structure inside as well. point coordinates are rarely used separately.

In my opinion, this is a fairly good example of the practical application of structures with regard to their features.

Microsoft has less successful examples, for example, the Control.Font property, in which it seems rather strange, not to be able to specify, for example, the Bold font attribute without replacing the entire Font structure, but if you look closely at the source, you will notice that this property is related to unmanaged WinAPI code and, most likely, there wasn’t much choice, except for the “quickly gash new API” option, which is of course unrealistic in practice.

Use the available tools for their intended purpose (in different languages ​​it may be different, this is normal).