Another reason structures are bad

    Faced at work with an interesting point of view. In the project, all the slightest data transfer objects are made by structures. When asked why this was done, I received the answer that in this way the data is protected from changes. On the one hand, yes, it sounds, in principle, logical, any methods receive only a copy and are not able to replace anything.

    But on the other hand, this approach carries far more problems than it solves.

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

    Secondly, the use of structures is fraught with errors. For instance:

    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.


    The screen will display, of course,
    10
    5
    

    But the fact that this “course” will become clear only after a careful study of the code, and, only with the 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, incidentally, is eloquently echoed by the bug in Resharper - he suggests replacing the 'for' loop with 'foreach', which, it turns out, is impossible).

    And thirdly, in fact, the feeling of "security" is deceptive. Arrays are often found in these structures (even if there are structures), which makes these “immutable” structures not “immutable” at all. For instance:
    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 be even obvious if Foo was not a structure, but a class. But in the case of structures, to understand that the developer wanted to change the value in the array, but did not fall into the trap of pseudo-invariance, again, it is very, very difficult.

    The conclusions suggest themselves (of course, no one canceled common sense and special 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 or as a last resort IList (but only as ReadOnlyCollection)
    3. If you really use structures, make them truly immutable.

    Also popular now: