We have seen lots of discussion in SO regarding the class vs struct in c#. Mostly ended with conclusions saying its a heap/stack memory allocation. And reco
structs should be defined immutable where in classes should not. If you think your objects are going to be small and immutable you can go ahead with making them structs or else let them be classes.
A class object has the advantage that it's possible to pass around a reference to it, with the scope and lifetime of such a reference being unlimited if it reaches outside code. A struct has the advantage that while it's possible to pass around short-lived references to them, it's not possible to pass around perpetual promiscuous references. This helps avoid having to worry about whether such references exist.
Some people have suggested that data holders which are mutable should not be structs. I emphatically disagree. Entities which exists for the purpose of holding data should, in many cases, be structs, especially if they are mutable. Eric Lippert has posted many times that he considers mutable value types evil (search under tags "mutable" and "struct"). It is certainly true that .net allows certain things to be done with mutable structs which it shouldn't, and doesn't conveniently allow some things that it should, but POD ("Plain Old Data") structs which have no mutating methods, but instead expose their entire state via public fields, have a very useful consistency in their behavior which is not shared with any other data type. Using a POD struct may confuse someone who isn't familiar with how they work, but will make the program much more readable by anyone who does.
Consider, for example, the following code, assuming EmployeeInfoStruct contains nothing but value types and immutable class types like String:
[employeeInfoStruct is a struct containing the following field] public Decimal YearlyBonus; [someEmployeeContainer is an instance of a class which includes the following method] EmployeeInfoStruct GetEmployeeInfo(String id); // Just the signature--code is immaterial [some other method uses the following code] EmployeeInfoStruct anEmployee = someEmployeeContainer.GetEmployeeInfo("123-45-6789"); anEmployee.YearlyBonus += 100;
Eric Lippert complains that the above code will alter the value in anEmployee, but that change won't have any effect on the container. I would suggest that's a good thing--anyone who knows how structs work could look at the above code and know writes to a struct variable will affect that variable, but won't affect anything else unless the program later uses some other method (perhaps SetEmployeeInfo) to store that variable someplace.
Now replace EmployeeInfoStruct with EmployeeInfoClass, which has a read/write property of type YearlyBonus. Using just the information above, what can one say about the the relationship between writes to someEmployeeContainer and anEmployee? Depending upon the implementations of anEmployee's class (which, unless EmployeeInfoClass is sealed, might or might not actually be EmployeeInfoClass) and someEmployeeContainer, the relationship between the objects could be anything. Writes to one might:
With structs containing nothing but fields of either value types or immutable classes, the semantics are always going to be #1. One doesn't have to look at the code for the struct itself, nor the code of the container, to know that. By contrast, if the anEmployee.Salary or someEmployeeContainer.GetEmployee is virtual, it's impossible to really know what the semantics will be.
It's important to note that, if structs are large, passing them by value or returning them from functions can be expensive. It's generally better to pass large structs as ref
parameters when possible. Although the built-in collections really don't do a good job of facilitating such usage, it can make using a hundreds-of-bytes struct cheaper than using a class.
The comment about structs being immutable is correct. And this is where it can bite you. You can define structs with field setters, but when you change a field value a new instance is created. So if you hold a reference to the old object it will still reference the old value. I don't like using mutable stucts for this reason as this can produce subtle and complex bugs (especially if you use complex compound statements).
On the other hand, there are lots of good reasons for using classes with immutable state also (think string).