Why is this implemented as a structure?

System.Data.Linq EntitySet<T> uses several ItemList<T> structures, which look like this:

  internal struct ItemList<T> where T : class { private T[] items; private int count; ...(methods)... } 

(It took me longer than necessary to detect this - I could not understand why the object field in EntitySet<T> did not throw unnecessary reference exceptions!)

My question is, what are the advantages of implementing this as a structure over a class?

+43
c # struct linq
Jun 01 2018-11-11T00:
source share
5 answers

Suppose you want to store an ItemList<T> in an array.

Allocating an array of value types ( struct ) will store the data inside the array. If, on the other hand, ItemList<T> was a reference type ( class ), only references to ItemList<T> objects will be stored inside the array. Actual ItemList<T> objects will be allocated on the heap. Reaching an instance of ItemList<T> requires an additional level of indirection, and since it simply represents an array combined with a length, it is more efficient to use the value type.

Struct vs class

After checking the code for EntitySet<T> I see that the array is not involved. However, EntitySet<T> still contains two instances of ItemList<T> . Because ItemList<T> is a struct , the storage for these instances is allocated inside the EntitySet<T> . If class used instead, then the EntitySet<T> would contain links pointing to EntitySet<T> objects that were highlighted separately.

The difference in performance between using one or the other may not be noticeable in most cases, but perhaps the developer decided that he wanted to treat the array and closely related count as one value simply because it seemed to be the best thing to do.

+34
Jun 01 2018-11-11T00:
source share

For small critical internal data structures, such as ItemList<T> , we often have the choice of using either a reference type or a value type. If the code is well written, the transition from one to another has a trivial change.

We can assume that the value type avoids the allocation of the heap and the reference type avoids structuring, so it is not immediately cleared in any case, because it depends so much on how it is used.

The best way to find out which one is better is to measure it . The faster, the better the winner. I'm sure they benchmarked, and struct is faster. After you have done this several times, your intuition is very good, and the standard simply confirms that your choice was the right one.

+9
Jun 01 2018-11-11T00:
source share

Perhaps it is important that ... a quote about the structure from here

The new variable and the original variable therefore contain two separate copies of the same data. Changes made to one copy do not affect another copy .

Just think, don't judge me hard :)

+6
Jun 01 2018-11-11T00:
source share

In fact, there are only two reasons why you should ever use a structure, and this is either to get value type semantics, or to improve performance.

Since the structure contains an array, value type semantics do not work. When you copy the structure, you get a copy of count , but you only get a copy of the reference to the array, not a copy of the elements in the array. Therefore, you will have to use extreme caution whenever the structure is copied so that you do not receive conflicting instances.

So the only remaining valid reason will be performance. There is a small overhead for each instance of the reference type, so if you have a lot of them, there can be a noticeable increase in performance.

One of the great features of this structure is that you can create an array from them and you will get an array of empty lists without having to initialize each list:

 ItemList<string>[] = new ItemList<string>[42]; 

Since the elements of the array are filled with zeros, the count member will be zero, and the items member will be null.

+5
Jun 01 2018-11-11T00:
source share

Thinking purely here:

Since the object is quite small (it has only two member variables), it is a good candidate to make it struct so that it is passed as a ValueType .

In addition, as @Martin Liversage points out, being a ValueType , it can be stored more efficiently in large data structures (for example, as an element in an array), without the overhead of having a separate object and referencing it.

+2
Jun 01 '11 at 6:45
source share



All Articles