Questions about Structs
Asked Answered
D

7

7

MSDN says that a class that would be 16 bytes or less would be better handled as a struct [citation].
Why is that?
Does that mean that if a struct is over 16 bytes it's less efficient than a class or is it the same?
How do you determine if your class is under 16 bytes?
What restricts a struct from acting like a class? (besides disallowing parameterless constructors)

Dilemma answered 20/3, 2009 at 18:2 Comment(3)
You can find a lot of information on C# structs here: #86053Matusow
You've probably already found it, but there's a ton more in the MSDN, here: msdn.microsoft.com/en-us/library/ms229017.aspxMatusow
I just found that right before you posted it. Thanks!Dilemma
W
7

There are a couple different answers to this question, and it is a bit subjective, but some reasons I can think of are:

  • structs are value-type, classes are reference type. If you're using 16 bytes for total storage, it's probably not worth it to create memory references (4 to 8 bytes) for each one.
  • When you have really small objects, they can often be pushed onto the IL stack, instead of references to the objects. This can really speed up some code, as you're eliminating a memory dereference on the callee side.
  • There is a bit of extra "fluff" associated with classes in IL, and if your data structure is very small, none of this fluff would be used anyway, so it's just extra junk you don't need.

The most important difference between a struct and a class, though, is that structs are value type and classes are reference type.

Welford answered 20/3, 2009 at 18:15 Comment(4)
Oh! sorry - should have written "Intermediate Language", which is kind of a shorthand for the whole "CLR", common language runtime - it's the virtual machine that runs .NET code.Welford
That's exactly right, Freddy Rios. In the .NET world, people often say "IL" when they mean "CLR". A great book on the topic is "Inside Microsoft .NET IL Assembler" by Serge Lidin. See amazon.com/Inside-Microsoft-NET-IL-Assembler/dp/0735615470Welford
Mike: Just nit-picking your comment here ;) - IL is the actual byte code, where the CLR is the runtime that executes the IL. They are 2 separate concepts.Ussery
@Welford I know well the .net side of it, it is java side than I am less used to :)Turves
T
3

By "efficient", they're probably talking about the amount of memory it takes to represent the class or struct.

On the 32-bit platform, allocating an object requires a minimum of 16 bytes. On a 64-bit platform, the minimum object size is 24 bytes. So, if you're looking at it purely from the amount of memory used, a struct that contains less than 16 bytes of data will be "better" than the corresponding class.

But the amount of memory used is not the whole story. Value types (structs) are fundamentally different than reference types (classes). Structs can be inconvenient to work with, and can actually cause performance problems if you're not careful.

The real answer, of course, is to use whichever works best in your situation. In most cases, you'll be much better off using classes.

Thigh answered 20/3, 2009 at 18:48 Comment(0)
F
2

Check this link, I found it on one of the answers in SO today: .NET Type Internals. You can also try searching SO and Googling for "reference types vs value types" for differences between structs and classes.

What restricts a struct from acting like a class?

There are many differences. You cannot inherit from a struct, for example.

You can't have virtual methods, so you cannot use a struct to implement an interface. Instance methods in structs can access struct's private fields, but apart from that they behave a lot like auxilirary "helper" functions (for immutable structs, they sometimes don't even need to access private data). So I find them to be not as near as "valuable" as class methods.

Floatfeed answered 20/3, 2009 at 18:15 Comment(2)
"not much benifit in adding instance methods to a struct" -- Can you expand on this further? I have found it mildy usefull, i.e. adding a ToString()Reprieve
@Neil: I rephrased it a bit, sorry for the poor choice of words.Floatfeed
S
1

structs are different from classes because they are stored on the stack, and not on the heap. That means that every time you call a method with the struct as parameter, a copy is created and passed to the method. That is why large structs are extremely inefficient.

I would actively discourage to use structs nevertheless, because it could cause some subtle bugs: e.g. when you change a field of a struct, its not going to be reflected for the caller (because you only changed the copy) - which is completely different behavior to classes.

So the 16 bytes I think is a reasonable maximum size of a struct, but still in most cases it is better to have a class. If you still want to create a struct, try to make it immutable at least.

Strainer answered 20/3, 2009 at 18:17 Comment(0)
T
0

In memory, the struct will hold the data directly, while a class will behave more like a pointer. That alone makes an important difference, since passing the struct as a parameter to a method will pass its values (copy them on the stack), while the class will pass the reference to the values. If the struct is big, you will be copying a lot of values on each method call. When it is really small copying the values and using them directly will be probably faster than copying the pointer and having to grab them from another place.

About restrictions: you can't assign it to null (although you can use Nullable<>) and you have to initialize it right away.

Turves answered 20/3, 2009 at 18:13 Comment(2)
MSDN says a Struct is stored on stack, while a class is stored on the heap.Dilemma
Yes, that's true. Stack variables can be traversed faster than heap variables. But when you pass a struct as a parameter to a method, it will be copied to the stack completely before the method is called, while for a class only a pointer will be copied.Floatfeed
N
0

This is due to the different way that the CLR handles structs and classes. Structs are value types which means they live on the stack rather than in the managed heap. It is a good rule of thumb to keep structs small because once you start passing them as method arguments you will incur overhead as structs are copied in their entirety when passed to a method.

Since classes pass a copy of their reference to methods they incur much less overhead when used as method arguments.

The best way to determine the size of your class is to total the number of bytes required by all the members of your class plus an extra 8 bytes for CLR overhead stuff (the sync block index and the reference to the type of the object).

Notch answered 20/3, 2009 at 18:16 Comment(0)
F
0

Copying an instance of a struct takes less time than creating a new instance of a class and copying data from an old one, but class instances can be shared and struct instances cannot. Thus, "structvar1 = structvar2" requires copying new struct instance, whereas "classvar1 = classvar2" allows classvar1 and classvar2 refer to the same struct instance (without having to create a new one).

The code to handle the creation of new struct instances is optimized for sizes up to 16 bytes. Larger structs are handled less efficiently. Structs are a win in cases where every variable that holds a struct will hold an independent instance (i.e. there's no reason to expect that any particular two variables will hold identical instances); they are not much of a win (if they're a win at all) in cases where many variables could hold the same instance.

Fears answered 20/1, 2011 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.