Questions in line

Our application has a queue, which is defined as:

private static Queue RawQ = new Queue(); 

Then two different types of objects are placed in the queue: one of the objects of the class ( class A ), and one - objects from the structure ( struct B ).

When we process data from a queue, we use typeof to verify that the element from the queue is of type (class A or struct B).

My questions:

  • for objects from class A, only their references are copied to the queue and for objects from structure B, their values ​​are copied to the queue, am I right?
  • for the queue, some elements are links that are small, and some elements are values ​​that are much larger (about 408 bytes). Will it lose a lot of memory if the queue is not small?
  • Do you have a better way to do the same?

thanks,

+4
source share
4 answers

for objects from class A, only their references are copied to the queue and for objects from structure B, their values ​​are copied to the queue, am I right?

Right. In fact, when you add structure B to the queue, it is first placed in the box. In other words, instance B is copied to the managed heap, and the link to the copy is placed in the queue.

for the queue, some elements are links that are small, and some elements are values ​​that are much larger (about 408 bytes). Will it lose a lot of memory if the queue is not small?

Perhaps - in boxing, instance B takes a copy that uses more memory than it does not. It depends on what happens with the original.

408 bytes is very large for a .NET structure; the general rule is that structures should not exceed 16 bytes . The reason is similar to this: large structures introduce overhead due to copying and boxing.

Do you have a better way to do the same?

I would ask if B should be a structure in the first place. Another rule of thumb (mine, this time): you probably won't need a structure in .NET code.

+3
source

1. for objects from class A, only their references are copied to the queue and for objects from structure B, their values ​​are copied to the queue, am I right?

It is right. Except that the value types will be boxed.

2. For the queue, some elements are links that are small, and some elements are values ​​that are much larger (about 408 bytes). Will it be wasteful of memory space if the queue is not small?

This is mostly true. Boxing will add another 8 bytes (4 for the sync block and 4 for type information), so for large structures that are insignificant, but for smaller structures that will represent a larger coefficient.

3. Do you have a better way to do the same?

The best thing to do is to convert this large structure into a class. There is no hard rule to know when to choose a structure or class based on size, but 32 bytes seems to be a common threshold. Of course, you can easily justify large structures based on whether you really need value type semantics, but 408 bytes probably go beyond that threshold. If a type really needs value semantics, you can make it an immutable class.

Another change you could make is to use the Queue generic class instead. Value types do not fit in the box, as they would with a regular Queue . However, you will still copy this large structure even with the general version.

+2
source

From C # spec :

Since structures are not reference types, these operations are performed differently for structure types. When a value of type struct is converted to a type or type of interface that is implemented by the structure, a boxing operation takes place.

So, to answer 1) the queue contains nested structures, not the actual values ​​of the structure.

The answer to 2) falls out of this, the structure in the block and the link are the same size in the actual queue distribution.

For 3) I need more information. It would be preferable to have the same type in the queue and have polymorphic operations that are handled by both classes and structures accordingly. Redundant case statements and typeof () calls show that your program is more procedural than object oriented. This may be what you want, but C # is optimized for the OO approach.

+2
source

I tried to check this twice, but here is what I feel:

The System.Collections.Queue class contains a collection of type Object , which is a reference type. Therefore, when you pass a Struct instance in turn, it is placed as an object. This creates a copy on the heap and provides a refernce pointer (this is what the queue sees). Thus, the queue itself does not get too large, but if you perform many such operations, you end up (according to Microsoft) with memory and performance in boxing / unboxing.

See the C # Language Specification for more details.

+1
source

All Articles