Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

What are your rules of thumb for when to use structs vs. classes? I'm thinking of the C# definition of those terms but if your language has similar concepts I'd like to hear your opinion as well.

I tend to use classes for almost everything, and use structs only when something is very simplistic and should be a value type, such as a PhoneNumber or something like that. But this seems like a relatively minor use and I hope there are more interesting use cases.

share|improve this question
3  
3  
@Frustrated Can't mark a question as a duplicate of something on another site, although it is certainly related. –  Anna Lear Jul 12 '11 at 17:28
    
@Anna Lear: I know, I voted to migrate not to close-as-duplicate. Once it's migrated, it can be closed as a duplicate properly. –  FrustratedWithFormsDesigner Jul 12 '11 at 17:32
1  
@Frustrated I don't think it needs to be migrated. –  Anna Lear Jul 12 '11 at 17:35
6  
This seems like a question much more suited to P.SE vs. SO. Which is why I asked it here. –  RationalGeek Jul 12 '11 at 17:46

5 Answers 5

up vote 55 down vote accepted

The general rule to follow is that structs should be small, simple (one-level) collections of related properties, that are immutable once created; for anything else, use a class.

C# is nice in that structs and classes have no explicit differences in declaration other than the defining keyword; so, if you feel you need to "upgrade" a struct to a class, or conversely "downgrade" a class to a struct, it's mostly a simple matter of changing the keyword (there are a few other gotchas; structs can't derive from any other class or struct type, and they can't explicitly define a default parameterless constructor).

I say "mostly", because the more important thing to know about structs is that, because they are value types, treating them like classes (reference types) can end up a pain and a half. Particularly, making a structure's properties mutable can cause unexpected behavior.

For example, say you have a class SimpleClass with two properties, A and B. You instantiate a copy of this class, initialize A and B, and then pass the instance to another method. That method further modifies A and B. Back in the calling function (the one that created the instance), your instance's A and B will have the values given to them by the called method.

Now, you make it a struct. The properties are still mutable. You perform the same operations with the same syntax as before, but now, A and B's new values aren't in the instance after calling the method. What happened? Well, your class is now a struct, meaning it's a value type. If you pass a value type to a method, the default (without an out or ref keyword) is to pass "by value"; a shallow copy of the instance is created for use by the method, and then destroyed when the method is done leaving the initial instance intact.

This becomes even more confusing if you were to have a reference type as a member of your struct (not disallowed, but extremely bad practice in virtually all cases); the class would not be cloned (only the struct's reference to it), so changes to the struct would not affect the original object, but changes to the struct's subclass WILL affect the instance from the calling code. This can very easily put mutable structs in very inconsistent states that can cause errors a long way away from where the real problem is.

For this reason, virtually every authority on C# says to always make your structures immutable; allow the consumer to specify the properties' values only on construction of an object, and never provide any means to change that instance's values. Readonly fields, or get-only properties, are the rule. If the consumer wants to change the value, they can create a new object based on the values of the old one, with the changes they want, or they can call a method which will do the same. This forces them to treat a single instance of your struct as one conceptual "value", indivisible and distinct from (but possibly equatable to) all others. If they perform an operation on a "value" stored by your type, they get a new "value" which is different from their initial value, but still comparable and/or semantically equatable.

For a good example, look at the DateTime type. You cannot assign any of the fields of a DateTime instance directly; you must either create a new one, or call a method on the existing one which will produce a new instance. This is because a date and time are a "value", like the number 5, and a change to the number 5 results in a new value that is not 5. Just because 5+1 = 6 doesn't mean 5 is now 6 because you added 1 to it. DateTimes work the same way; 12:00 does not "become" 12:01 if you add a minute, you instead get a new value 12:01 that is distinct from 12:00. If this is a logical state of affairs for your type (good conceptual examples that aren't built in to .NET are Money, Distance, Weight, and other quantities of a UOM where operations must take all parts of the value into account), then use a struct and design it accordingly. In most other cases where the sub-items of an object should be independently mutable, use a class.

share|improve this answer
    
Good answer! I'd point one reading it to 'Domain Driven Development' methodology and book, that seems somewhat related to your opinion about why one should use classes or structures based on which concept you actually trying to implement –  Max Jul 12 '11 at 18:31
    
Excellent answer thanks. –  RationalGeek Jul 12 '11 at 19:43
    
Just a little detail worth mentioning : you can't define your own default constructor on a struct. You have to make do with the one that initialize everything to its default value. Usually, that's pretty minor, especially on class that are good candidate to be a struct. But it will mean that changing a class to a struct may imply more than just changing a keyword. –  Laurent Bourgault-Roy Dec 20 '12 at 22:04
    
@LaurentBourgault-Roy - True. There are other gotchas as well; structs can't have an inheritance hierarchy, for instance. They can implement interfaces, but cannot derive from anything other than System.ValueType (implicitly by their being structs). –  KeithS Dec 20 '12 at 22:15
    
As a JavaScript dev I have to ask two things. How are object literals that different from typical usages of structs and why is it important that structs be immutable? –  Erik Reppen Dec 21 '12 at 5:50

I tend to use structs only when there is one method is needed thus making a class seems too "heavy". Thus sometimes I treat structs as lightweight objects. BEWARE: this does not always work and is not always the best thing to do, so it really depends on the situation!

EXTRA RESOURCES

For more formal explanation, MSDN says: http://msdn.microsoft.com/en-us/library/ms229017.aspx This link verifies what I mentioned above, structs should only be used for housing a small amount of data.

share|improve this answer
3  
Questions on another site (even if that site is Stack Overflow) don't count as duplicates. Please expand your answer to include an actual answer and not just links to other places. If the links ever change, your answer as it's written now will be useless and we like to preserve information and make Programmers as self-contained as possible. Thanks! –  Anna Lear Jul 12 '11 at 17:27
    
@Anna Lear Thanks for letting me know, will keep that in mind from now on! –  rrazd Jul 12 '11 at 17:37
    
No problem. Thanks for the edit. :) –  Anna Lear Jul 12 '11 at 17:37

Use a struct for pure data constructs, and a class for objects with operations.

If your data structure needs no access control and has no special operations other than get/set, use a struct. This makes it obvious that all that structure is is a container for data.

If your structure has operations that modify the structure in any more complex way, use a class. A class also can interact with other classes via arguments to methods.

Think of it as the difference between a brick and an airplane. A brick is a struct; it has lenght, width and height. It can't do much. An airplane could have multiple operations that mutate it somehow, like moving control surfaces and changing engine thrust. It would be better as a class.

share|improve this answer
    
"Use a struct for pure data constructs, and a class for objects with operations" in C# this is nonsense. See my answer below. –  nashwan Mar 25 at 16:38

The most important difference between a class and a struct is what happens in the following situation:

  Thing thing1 = new Thing();
  thing1.somePropertyOrField = 5;
  Thing thing2 = thing1;
  thing2.somePropertyOrField = 9;

What should be the effect of the last statement on thing1.somePropertyOrField? If Thing a struct, and somePropertyOrField is an exposed public field, the objects thing1 and thing2 will be "detached" from each other, so the latter statement will not affect thing1. If Thing is a class, then thing1 and thing2 will be attached to each other, and so the latter statement will write thing1.somePropertyOrField. One should use a struct in cases where the former semantics would make more sense, and should use a class in cases where the latter semantics would make more sense.

Note that while some people advise that a desire to make something mutable is an argument in favor of it being the class, I would suggest the reverse is true: if something which exists for the purpose of holding some data is going to be mutable, and if it will not be obvious whether instances are attached to anything, the thing should be a struct (likely with exposed fields) so as to make clear that instances are not attached to anything else.

For example, consider the statements:

  Person somePerson = myPeople.GetPerson("123-45-6789");
  somePerson.Name = "Mary Johnson"; // Had been "Mary Smith"

Will the second statement alter the information stored in myPeople? If Person is an exposed-field struct, it won't, and the fact that it won't will be an obvious consequence of its being an exposed-field struct; if Person is a struct and one wishes to update myPeople, one would clearly have to do something like myPeople.UpdatePerson("123-45-6789", somePerson). If Person is a class, however, it may be much harder to determine whether the above code would never update the contents of MyPeople, always update it, or sometimes update it.

With regard to the notion that structs should be "immutable", I disagree in general. There are valid usage cases for "immutable" structs (where invariants are enforced in a constructor) but requiring that an entire struct must be rewritten any time any part of it changes is awkward, wasteful, and more apt to cause bugs than would simply exposing fields directly. For example, consider a PhoneNumber struct whose fields, include among others, AreaCode and Exchange, and suppose one has a List<PhoneNumber>. The effect of the following should be pretty clear:

  for (int i=0; i < myList.Count; i++)
  {
    PhoneNumber theNumber = myList[i];
    if (theNumber.AreaCode == "312")
    {
      string newExchange = "";
      if (new312to708Exchanges.TryGetValue(theNumber.Exchange), out newExchange)
      {
        theNumber.AreaCode = "708";
        theNumber.Exchange = newExchange;
        myList[i] = theNumber;
      }
    }
  }

Note that nothing in the above code knows or cares about any fields in PhoneNumber other than AreaCode and Exchange. If PhoneNumber were a so-called "immutable" struct, it would be necessary either that it provide a withXX method for each field, which would return a new struct instance which held the passed-in value in the indicated field, or else it would be necessary for code like the above to know about every field in the struct. Not exactly appealing.

BTW, there are at least two cases where structs may reasonably hold references to mutable types.

  1. The semantics of the struct indicate that it's storing the identity of the object in question, rather than as a shortcut for holding the object's properties. For example, a `KeyValuePair` would hold the identities of certain buttons, but would not be expected to hold a persistent information about those button's positions, highlight states, etc.
  2. The struct knows that it holds the only reference to that object, nobody else will get a reference, and any mutations which will ever be performed to that object will have been done before a reference to it gets stored anywhere.

In the former scenario, the object's IDENTITY will be immutable; in the second, the class of the nested object may not enforce immutability, but the struct holding the reference will.

share|improve this answer

The answer: "Use a struct for pure data constructs, and a class for objects with operations" is definitely wrong IMO. If a struct holds a large number of properties then a class is nearly always more appropriate. Microsoft often says, from an efficiency point of view, if your type is larger than 16 bytes it should be a class.

http://msdn.microsoft.com/en-us/library/ah19swz4%28v=vs.71%29.aspx

share|improve this answer
    
Absolutely. I'd upvote if I could. I don't get where the idea came from that structs are for data and objects are not. A struct in C# is just a mechanism for allocating on the stack. Copies of the entire struct are passed around instead of just a copy of an object pointer. –  mike30 Dec 20 '12 at 17:30
    
@mike - C# structs are not necessarily allocated on the stack. –  Lee Dec 20 '12 at 18:37
    
@mike The "structs are for data" idea probably comes from the habit acquired by many years of C programming. C has no classes and its structs are data-only containers. –  Konamiman Dec 21 '12 at 11:07
    
Obviously there are at least 3 C programmers (got upvoted) having read Michael K's answer ;-) –  nashwan Jan 10 '13 at 16:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.