views:

660

answers:

8

Duplicate of: When to use struct in C#?

Are there practical reasons to use structures instead of some classes in Microsoft .NET 2.0/3.5 ?

"What is the difference between structures and classes?" - this is probably the most popular question on intrviews for ".NET developer" vacancies. The only answer that interviewer considers to be right is "structures are allocated on stack and classes are allocated on heap" and no further questions are asked about that.

Some google search showed that a) structures have numerous limitations and no additional abilities in comparison to classes and b) stack (and as such structures) can be faster on very specialized conditions including:

  • size of data chunk less that 16 bytes
  • no extensive boxing/unboxing
  • structure's members are nearly immutable
  • whole set of data is not big (otherwise we get stack overflow)

(please correct/add to this list if it is wrong or not full)

As far as I know, most typical commercial projects (ERM, accouting, solutions for banks, etc.) do not define even a single structure, all custom data types are defined as classes instead. Is there something wrong or at least imperfect in this approach?

NOTE: question is about run-of-the-mill business apps, please don't list "unusual" cases like game development, real-time animation, backward compatibility (COM/Interop), unmanaged code and so on - these answers are already under this similar question:

http://stackoverflow.com/questions/521298/when-to-use-struct-in-c

A: 

IMHO, structs are only used for performance improvement when you need a very small, simple value type.

Calls to members are also faster.

It might be also convenient when you don't need to care about references, and always get a new instance. This way, you never have side-effects when changing an instance which is referenced somewhere else. But this shouldn't be the main reason to use structs.

Stefan Steinegger
+1  A: 

Another difference with classes is that when you assign an structure instance to a variable, you are not just copying a reference but indeed copying the whole structure. So if you modify one of the instances (you shouldn't anyway, since structure instances are intended to be immutable), the other one is not modified.

Konamiman
See my post below. It's a can of worms. There is nothing inherent about value types or references types being, well, immutable. (Although I do prefer code which minimizes state mutations.)
pst
+7  A: 

IMO the most important use case are large arrays of small composite entities. Imagine an array containing 10^6 complex numbers. Or a 2d array containing 1000x1000 24-bit RGB values. Using struct instead of classes can make a huge difference in cases like these.

EDIT: To clarify: Assume you have a struct

struct RGB 
{
   public byte R,G,B;
}

If you declare an array of 1000x1000 RGB values, this array will take exactly 3 MB of memory, because the values types are stored inline.

If you used a class instead of a struct, the array would contain 1000000 references. That alone would take 4 or 8 MB (on a 64 bit machine) of memory. If you initialized all items with separate objects, so you can modify the values separately, you'd habe 1000000 objects swirling around on the managed heap to keep the GC busy. Each object has an overhead (IIRC) of 2 references, i.e. the objects would use 11/19 MB of memory. In total that's 5 times as much memory as the simple struct version.

nikie
Can you explain what difference structs would make and why?
gWiz
nikie: Thank you for precise amounts of memory used. But how many business applications work with this kind of data? (what you described in your example is image, isn't it?)
Mikhail
@Mikhail, I guess the limited need for structs explains why they aren't used much.
JonB
I like this example -- it avoids the programming differences between struct and object differences otherwise. In special cases, as this, **where the struct is stored in an array**, the CLR is able to realize more efficient memory usage (whether or not this matters is specific upon application and target).
pst
+4  A: 

One advantage of stack allocated value types is that they are local to the thread. That means that they are inherently thread safe. That cannot be said for objects on the heap.

This of course assumes we're talking about safe, managed code.

Brian Rasmussen
Could you clarify that? Isn't anything allocated from within the thread and not referenced externally is in the same boat though? Whether value or reference type. If I "new" an object from within a thread then other threads don't know where it is to trash it so it's just as safe isn't it?
JonB
True, but there is no way values on the stack can "escape" in managed code. Objects may be exposed through various means. If they are not, everything is fine, but you have to verify this yourself. With value types it is guaranteed not to happen.
Brian Rasmussen
In general this is true but not all value types are allocated on the stack and as soon as you are using pointers in C# your thread-safety is gone here.
Foxfire
@Foxfire: That is correct. If you use unsafe in your code it's a different set of rules.
Brian Rasmussen
Please leave a comment when down voting.
Brian Rasmussen
A: 

sometime, you just wanna transfer data between components, then struct is better than class. e.g. Data Transfer Object(DTO) which only carry data.

Benny
+9  A: 

As far as I know, most typical commercial projects (ERM, accouting, solutions for banks, etc.) do not define even a single structure, all custom data types are defined as classes instead. Is there something wrong or at least imperfect in this approach?

No! Everything is perfectly right with that. Your general rule should be to always use objects by default. After all we are talking about object-oriented programing for a reason and not structure-oriented programing (structs themselves are missing some OO principles like Inheritance and Abstraction).

However structures are sometimes better if:

  • You need precise control over the amount of memory used (structures use (depending on the size) a little bit to FAR less memory than objects.
  • You need precise control of memory layout. This is especially important for interop with Win32 or other native APIs
  • You need the fastest possible speed. (In lots of scenarios with larger sets of data you can get a decent speedup when correctly using structs).
  • You need to waste less memory and have large amounts of structured data in arrays. Especially in conjunction with Arrays you could get huge amount of memory savings with structures.
  • You are working extensively with pointers. Then structures offer lots of interesting characteristics.
Foxfire
Care to explain what nakes a struct inhertly non object oriented?
SDX2000
Why was that downvoted? All the advantages of structs seem correct, and I'd agree to the general rule of thumb, too.
nikie
I object to the statement "After all we are talking about object-oriented programing for a reason and not structure-oriented programing." Using structs does not make it non-OO.
SDX2000
I will remove the downvote if this is corrected
SDX2000
They are inherently non-oo because structures will ALWAYS be copy-by-value. The usual copy-by-ref is not existing/possible for struct. So if you want to have e.g. two houses that relate to one street thats impossible to design if both were structures because the houses would have 2 different (although content-identical) copies of the street struct.
Foxfire
And of course structures also miss the typical OO principles Inheritance and Abstraction.
Foxfire
I am not sure I follow your line of thought...I am assuming you have a stuct `House` with a field called `Street`...Why is it necessary for the Street field to refer to the same instance of the Street struct? Identical street values should be good enough...There may be some limitations while (equality vs identity issues for example) using structs but IMO these do not prevent it from being OO.
SDX2000
Ah...ok I forgot all about the inheritance issue with structs...so you are right they are not object oriented but they still are object based http://en.wikipedia.org/wiki/Object-based Abstraction is still supported by way of encapsulation (private members).
SDX2000
I tried to remove the downvote but SO says its too late for that! Sorry about this. I will revote in the future if there are any edits made to the answer.
SDX2000
I'l do an edit. And it seems you confused Abstaction with Encapsulation. Structs do support Encapsulation, but not Abstraction (which means you define e.g. an abstract method and later implement it in an inherited class)
Foxfire
Abstraction http://en.wikipedia.org/wiki/Abstraction is a catch all phrase it includes many techniques (including encapsulation).
SDX2000
I'd recommend http://en.wikipedia.org/wiki/Object-oriented_programming which also has a part about Abstraction in the context of OO
Foxfire
Fair enough! :)
SDX2000
+1Although, structs do actually support abstraction via interfaces. Unfortunately they get boxed when you access them via the interface. I *think* this can be avoided if you use generics instead.I tend to use structs for mathematically stuff (like Vector3 for three doubles) with operator overloads, etc
Jacob Stanley
I think that in addition to the reasons given, Eric Lippert (i think) pointed out a good reason on his blog: "Do you need access to *the* instance of a 2-component vector with values 10 and 5, or: Is the object you're designing semantically a value or semantically an object that holds attributes and values of it's own?" (not his exact words)
RCIX
@Jacob: You are right with the "mathematical stuff". However I was unsure about how to describe this. I thought about when there is no difference between identity and equality. But was not really happy with that either.
Foxfire
+1  A: 

All good answers thus far...I only have to add that by definition value types are not nullable and hence are a good candidate for use in scenarios where you do not want to be bothered with creating a new instance of a class and assigning it to fields, for example...

struct Aggregate1
{
    int A;
}

struct Aggregate2
{
    Aggregate1 A;
    Aggregate1 B;
}

Note if Aggregate1 were a class then you would have had to initialize the fields in Aggregate2 manually...

Aggregate2 ag2 = new Aggregate2();
ag2.A = new Aggregate1();
ag2.B = new Aggregate1();

This is obviously not required as long as Aggregate1 is a struct...this may prove to be useful when you are creating a class/struct heirarchy for the express purpose of serialization/deserialization with the XmlSerializer Many seemingly mysterious exceptions will disappear just by using structs in this case.

SDX2000
Nullable<T>, where T is a value type.
pst
Yeah I know..its a special case...one that you should know is nullable if you are using it! Its a struct which receives special treatment from the compiler.
SDX2000
A: 
verbose