📜 ⬆️ ⬇️

Another reason why structures are bad

Faced a job with an interesting point of view. In the project, all the slightest data transfer objects are made structures. To the question why this was done, I received an answer that in this way the data is protected from changes. On the one hand, yes, it sounds, in principle, it is logical, any methods get only a copy and are unable to change anything.

But on the other hand, such an approach carries many more problems than it solves.

First, the use of structures beats both in performance and in memory. Each call is a copy, any array of structures is almost guaranteed to fall into the Large Object Heap, which will hit performance again (due to the increased time in the GC) and memory (a fragmented heap is very bad).

Secondly, the use of structures is fraught with errors. For example:
')
class Program
{
static void Main( string [] args)
{
Foo[] f = new [] { new Foo {Field = 5}};

for ( int i = 0; i < f.Length; i++)
{
Foo foo = f[i];
foo.Field = 10;
Console .WriteLine(foo.Field);
}

Console .WriteLine(f[0].Field);
}
}
struct Foo
{
public int Field;
}

* This source code was highlighted with Source Code Highlighter .


On the screen will be displayed, of course,
 ten
 five

But the fact that this “of course” will become clear only after a close examination of the code, and, only with IDE, to understand that Foo is a structure in any other viewer is almost impossible, especially if Foo is defined in another project. .NET developers are accustomed to operating with links (which, by the way, is eloquently spoken by a bug in Resharper - he suggests replacing the for loop with a foreach, which, it turns out, is impossible).

And thirdly, in fact, the feeling of “security” is deceptive. Often in these structures there are arrays (even if structures), which makes these “immutable” structures not at all “immutable”. For example:
class Program
{
static void Main( string [] args)
{
Foo f = new Foo
{
Field = 5,
Bars = new []
{
new Bar {Name = "My Name" }
}
};

BadFunction(f);
Console .WriteLine(f.Bars[0].Name);
}

private static void BadFunction(Foo foo)
{
foo.Field = 10;
foo.Bars[0] = new Bar {Name = "Other Name" };
}
}
struct Foo
{
public int Field;
public Bar[] Bars;
}
struct Bar
{
public string Name;
}

* This source code was highlighted with Source Code Highlighter .


After execution, you will see “Other Name”, which is absolutely logical and it would even be obvious if Foo were not a structure, but a class. But in the case of structures, it is clear that the developer wanted to change the value in the array, and did not fall into the trap of pseudo-variation, again, it’s not very simple.

The conclusions suggest themselves (of course, common sense and no one has canceled particular cases):
  1. Use structures only where it is really necessary and justified (P / Invoke, for example).
  2. Do not use arrays as return types - use IEnumerable <T> or at most IList <T> (but only as ReadOnlyCollection <T>).
  3. If you already use structures, make them truly immutable.

Source: https://habr.com/ru/post/103063/


All Articles