views:

330

answers:

6

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)

A: 

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.

eglasius
MSDN says a Struct is stored on stack, while a class is stored on the heap.
Malfist
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.
Groo
+1  A: 

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.

Groo
"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()
Neil N
Most classes should be sealed, but I see your point.
Malfist
@Neil: I rephrased it a bit, sorry for the poor choice of words.
Groo
+6  A: 

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.

Mike
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.
Mike
Okay, like the JVM?
Malfist
I think IL ~ java bytecode, and CLR ~ JVM
eglasius
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 http://www.amazon.com/Inside-Microsoft-NET-IL-Assembler/dp/0735615470
Mike
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.
Reed Copsey
@Mike I know well the .net side of it, it is java side than I am less used to :)
eglasius
A: 

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).

Andrew Hare
A: 

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 behaviour 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.

Grzenio
+3  A: 

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.

Jim Mischel