15

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:

When to use struct?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
coder
  • 185
  • 3
  • 12
  • 9
    "structures are allocated on stack and classes are allocated on heap". It's strange that interviewers consider that to be the right answer, because it's not a right answer. You should read http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx – Joren Oct 20 '09 at 09:11
  • @Joren thanks for the link...its a good read. – Sandeep Datta Oct 20 '09 at 09:15
  • 5
    It's amazing what some interviewers think is "the right answer" to any given question, and they can be quite hostile if you point out that their pet answer is wrong. What is more amazing is that interviewers ask questions in order to elicit specific answers; when I interview, I try to ask questions that test ability to reason intelligently about a realistic problem, resolve ambiguities and understand complex code. Spouting correct answers to trivia questions is not a core requirement of most development jobs. – Eric Lippert Oct 20 '09 at 18:06
  • Joren: it is considered to be right answer because Richter's "CLR via C#" book says it (briefly) and this book is The Bible for some (lots of?) interviewers. Eric: agree with you completely about (non)importance of trivias, but managed to find only several companies (in my region) that do not ask about trivias. – coder Oct 22 '09 at 12:33

8 Answers8

12

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
  • 5,675
  • 21
  • 29
  • Care to explain what nakes a struct inhertly non object oriented? – Sandeep Datta Oct 20 '09 at 09:12
  • Why was that downvoted? All the advantages of structs seem correct, and I'd agree to the general rule of thumb, too. – Niki Oct 20 '09 at 09:16
  • 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. – Sandeep Datta Oct 20 '09 at 09:20
  • I will remove the downvote if this is corrected – Sandeep Datta Oct 20 '09 at 09:20
  • 2
    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 Oct 20 '09 at 09:23
  • And of course structures also miss the typical OO principles Inheritance and Abstraction. – Foxfire Oct 20 '09 at 09:28
  • 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. – Sandeep Datta Oct 20 '09 at 09:37
  • 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). – Sandeep Datta Oct 20 '09 at 09:45
  • 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. – Sandeep Datta Oct 20 '09 at 09:48
  • 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 Oct 20 '09 at 09:55
  • Abstraction http://en.wikipedia.org/wiki/Abstraction is a catch all phrase it includes many techniques (including encapsulation). – Sandeep Datta Oct 20 '09 at 09:59
  • I'd recommend http://en.wikipedia.org/wiki/Object-oriented_programming which also has a part about Abstraction in the context of OO – Foxfire Oct 20 '09 at 10:03
  • +1 Although, 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 Oct 21 '09 at 08:13
  • 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 Oct 21 '09 at 08:20
  • @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 Oct 21 '09 at 10:30
8

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.

Niki
  • 15,662
  • 5
  • 48
  • 74
  • Can you explain what difference structs would make and why? – G-Wiz Oct 20 '09 at 09:02
  • 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?) – coder Oct 20 '09 at 09:51
  • @Mikhail, I guess the limited need for structs explains why they aren't used much. –  Oct 20 '09 at 10:20
  • 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). –  Oct 21 '09 at 06:11
6

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
  • 114,645
  • 34
  • 221
  • 317
  • 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? –  Oct 20 '09 at 09:33
  • 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 Oct 20 '09 at 09:53
  • 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 Oct 20 '09 at 10:02
  • @Foxfire: That is correct. If you use unsafe in your code it's a different set of rules. – Brian Rasmussen Oct 20 '09 at 10:19
  • Please leave a comment when down voting. – Brian Rasmussen Oct 21 '09 at 06:34
3

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
  • 49,681
  • 17
  • 108
  • 138
  • 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.) –  Oct 21 '09 at 06:33
1

If the purpose of a type is to bind a small fixed collection of independent values together with duct tape (e.g. the coordinates of a point, a key and associated value of an enumerated dictionary entry, a six-item 2d transformation matrix, etc.), the best representation, from the standpoint of both efficiency and semantics, is likely to be a mutable exposed-field structure. Note that this represents a very different usage scenario from the case where a struct represents a single unified concept (e.g. a Decimal or DateTime), and Microsoft's advice for when to use structures gives advice which is only applicable to the latter one. The style of "immutable" structure Microsoft describes is only really suitable for representing a single unified concept; if one needs to represent a small fixed collection of independent values, the proper alternative is not an immutable class (which offers inferior performance), nor a mutable class (which will in many cases offer incorrect semantics), but rather an exposed-field struct (which--when used properly--offers superior semantics and performance). For example, if one has a struct MyTransform which holds a 2d transformation matrix, a method like:

static void Offset(ref it, double x, double y)
{
  it.dx += x;
  it.dy += y;
}

is both faster and clearer than

static void Offset(ref it, double x, double y)
{
  it = new Transform2d(it.xx, int.xy, it.yx, it.yy, it.dx+x, it.dy+y);
}

or

Transform2d Offset(double dx, double dy)
{
  it = new Transform2d(xx, xy, yx, yy, dx+x, dy+y);
}

Knowing that dx and dy are fields of Transform2d is sufficient to know that the first method modifies those fields and has no other side-effect. By contrast, to know what the other methods do, one would have to examine the code for the constructor.

supercat
  • 77,689
  • 9
  • 166
  • 211
1

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.

Sandeep Datta
  • 28,607
  • 15
  • 70
  • 90
  • Nullable, where T is a value type. –  Oct 21 '09 at 06:16
  • 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. – Sandeep Datta Oct 21 '09 at 11:34
0

There have been some excellent answers that touch on the practicality of using structs vs. classes and visa-versa, but I think your original comment about structs being immutable is a pretty good argument for why classes are used more often in the high-level design of LOB applications.

In Domain Driven Design http://www.infoq.com/minibooks/domain-driven-design-quickly there is somewhat of a parallel between Entities/Classes and Value Objects/Structs. Entities in DDD are items within the business domain whose identity we need to track with an identifier, e.g. CustomerId, ProductId, etc. Value Objects are items whose values we might be interested in, but whose identity we don't track with an identifier e.g Price or OrderDate. Entities are mutable in DDD except for their Identity Field, while Value Objects do not have an identity.

So when modeling a typical business entity, a class is usually designed along with an identity attribute, which tracks the identity of the business object round trip from the persistance store and back again. Although at runtime we might change all the property values on a business object instance, the entity's identity is retained as long as the identifier is immutable. With business concepts that correspond to Money or Time, a struct is sort of a natural fit because even though a new instance is created whenever we perform a computation, that's ok because we aren't tracking an identity, only storing a value.

verbose
  • 143
  • 1
  • 1
  • 8
-3

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
  • 8,547
  • 9
  • 60
  • 93