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?

4
  • 10
    "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 blogs.msdn.com/ericlippert/archive/2009/04/27/… Commented Oct 20, 2009 at 9:11
  • @Joren thanks for the link...its a good read. Commented Oct 20, 2009 at 9:15
  • 6
    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. Commented Oct 20, 2009 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. Commented Oct 22, 2009 at 12:33

8 Answers 8

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.
Sign up to request clarification or add additional context in comments.

15 Comments

Care to explain what nakes a struct inhertly non object oriented?
Why was that downvoted? All the advantages of structs seem correct, and I'd agree to the general rule of thumb, too.
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.
I will remove the downvote if this is corrected
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.
|
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.

4 Comments

Can you explain what difference structs would make and why?
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, I guess the limited need for structs explains why they aren't used much.
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).
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.

5 Comments

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?
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.
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: That is correct. If you use unsafe in your code it's a different set of rules.
Please leave a comment when down voting.
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.

1 Comment

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

2 Comments

Nullable<T>, where T is a value type.
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.
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.

Comments

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.

Comments

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.