This question already has answers here:
When should I use a struct rather than a class in C#?
(31 answers)
Closed 9 years ago.
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?
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.
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.
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.
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.
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.
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.
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.
sometime, you just wanna transfer data between components, then struct is better than class. e.g. Data Transfer Object(DTO) which only carry data.
Related
Given that mutable structs are generally regarded as evil (e.g., Why are mutable structs “evil”?), are there potential benefits that might have prompted the designers of the .NET framework to make System.Windows.Point & System.Windows.Vector mutable?
I'd like to understand this so I can decide whether it would make sense to make my own similar structs mutable (if ever). It's possible the decision to make Point and Vector mutable was just an error in judgment, but if there was a good reason (e.g., a performance benefit), I'd like to understand what it was.
I know that I've stumbled over the implementation of the Vector.Normalize() method a few times because it, surprise (!), does not return a fresh Vector. It just alters the current vector.
I always think it should work like this:
var vector = new Vector(7, 11);
var normalizedVector = vector.Normalize(); // Bzzz! Won't compile
But it actually works like this:
var vector = new Vector(7, 11);
vector.Normalize(); // This compiles, but now I've overwritten my original vector
...so, it seems like immutability is a good idea simply for avoiding confusion, but again, perhaps it's worth that potential confusion in some cases.
These types are in the System.Windows namespace and are generally used in WPF applications. The XAML markup of an application is a big part of the framework so for a lot of things, they need a way to be expressed using XAML. Unfortunately there's no way to invoke non-parameterless constructors using WPF XAML (but it is possible in loose XAML) so trying to call a constructor with the appropriate arguments to initialize it wouldn't be possible. You can only set the values of the object's properties so naturally, these properties needed to be mutable.
Is this a bad thing? For these types, I'd say no. They are just for holding data, nothing more. If you wanted to get the size a Window wanted to be, you'd access the DesiredSize to get the Size object representing the size it wanted. You're not meant to "change the desired size" by altering the Width or Height properties of the Size object you get, you change the size by providing a new Size object. Looking at it this way is a lot more natural I believe.
If these objects were more complex and did more complicated operations or had state, then yes, you wouldn't want to make these types neither mutable nor structs. However since they're just about as simple and basic as it can get (essentially a POD), structs would be appropriate here.
Such types are mutable because, contrary to what some people might claim, mutable value-type semantics are useful. There are a few places where .net tries to pretend that value types should have the same semantics as reference types. Since mutable value-type semantics are fundamentally different from mutable reference-type semantics, pretending they're the same will cause problems. That doesn't make them "evil", however--it merely shows a flaw in an object model which assumes that acting upon a copy of something will be semantically equivalent to acting upon the original. True if the thing in question is an object reference; generally true--but with exceptions--if it's an immutable structure; false if it's a mutable structure.
One of the beautiful things about structs with exposed fields is that their semantics are readily ascertained by even simple inspection. If one has a Point[100] PointArray, one has 100 distinct instances of Point. If one says PointArray[4].X = 9;, that will change one item of PointArray and no other.
Suppose instead of using struct Point, one had a mutable class PointClass:
class PointClass {public int X; public int Y;};
How many PointClass instances are stored in PointClass[100] PointClassArray? Is there any way to tell? Will the statement PointClass[4].X = 9 affect the value of PointClass[2].X? What about someOtherObject.somePoint.X?
While the .net collections are not well suited to storage of mutable structs, I would nonetheless regard:
Dictionary<string, Point>;
...
Point temp = myDict["George"];
temp.X = 9;
myDict["George"] = temp;
to have relatively clear semantics, at least in the absence of threading issues. While I consider it unfortunate that .net collections don't provide a means by which one could simply say myDict[lookupKey].X = 9; I would still regard the above code as pretty clear and self-explanatory without having to know anything about Point other than the fact that it has a public integer field called X. By contrast, if one had a Dictionary<PointClass>, it would be unclear what one should be expected to do to change the X value associated with "George". Perhaps the PointClass instance associated with George is not used anywhere else, in which case one may simply write the appropriate field. On the other hand, it's also possible that someone else has grabbed a copy of MyDict["George"] for the purpose of capturing the values therein, and isn't expecting that the PointClass object he's grabbed might change.
Some people might think "Point" should be an immutable struct, but the effect of a statement like somePoint.X = 5; can be fully determined knowing only that somePoint is a variable of type Point, which in turn is a struct with a public int field called X. If Point were an immutable struct, one would have to instead say something like somePoint = new Point(5, somePoint.Y);, which would, in addition to being slower, require examining the struct to determine that all of its fields are initialized in the constructor, with X being the first and Y the second. In what sense would that be an improvement over somePoint.X = 5;?
BTW, the biggest 'gotcha' with mutable structs stems from the fact that there's no way for the system to distinguish struct methods which alter 'this' from those which do not. A major shame. The preferred workarounds are either to use functions which return new structs derived from old ones, or else use static functions which accept "ref" struct parameters.
Possibilities:
It seemed like a good idea at the time to someone who didn't consider the use-cases where it would bite people. List<T>.Enumerator is a mutable struct that was used because it seemed like a good idea at the time to take advantage of the micro-opts that would often happen. It's almost the poster-child for mutable structs being "evil" as it's bitten more than a few people. Still, it seemed like a good idea to someone at the time...
They did think of the downsides, but had some use-case known to them where the performance differences went in struct's favour (they don't always) and was considered important.
They didn't consider structs evil. "Evil" is an opinion about down-sides beating up-sides, not a demonstrable fact, and not everyone has to agree with something even if Eric Lippert and Jon Skeet say it. Personally I think they're not evil, they're just misunderstood; but then again, evil is often easier to deal with than misunderstood for a programmer, so that's actually worse... ;) Maybe those involved disagree.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Which is best for data store Struct/Classes?
Consider the example where I have an Employee object with attributes like age, name, gender, title, salary. I now have a list i want to populate with a bunch of Employees (each Employee instance is unique).
In terms of just speed and memory footprint, is it more preferable to create the employee as a Struct or a Class?
Any additional caveats regarding Struct vs Class in the above scenario are welcome
Structs are to be used only for relatively small structures that should have value-like behaviour.
Class and struct differences
Choosing Between Classes and Structures
Do not define a structure unless the type has all of the following
characteristics:
It logically represents a single value, similar to primitive types
(integer, double, and so on).
It has an instance size smaller than
16 bytes.
It is immutable.
It will not have to be boxed frequently.
Your type breaks the first two guidelines, and probably also the third. So you should definitely use a class here.
It isn't as simple as that - you need to describe the behaviour. For example, a struct will copy itself as soon as you like, so in some ways they can consume more memory. However, an array of structs as a raw data dump can avoid a (very small) object header (and an extra dereference), so can have efficiencies.
A bigger issue, though, is in how you conceptualise them; an Employee is not a value; if I assign:
var emp = GetEmployee();
var tmp = emp;
does that mean I should now have 2 employees? It proabably doesn't. Now what if I change:
tmp.Name = "Fred";
whether this impacts emp depends on whether it is struct or class. I wager it should be class here. I also propose that a struct should almost always be immutable to avoid this type of data-loss scenario. There is case for mutable structs, but it is so often used incorrectly that I don't want to accidentally encourage you to do that.
Other issues arise with encapsulation with structs; consider that an employee has a manager; is this possible?
[struct|class] Manager {
private Manager boss;
}
this only works for a class. Again; structs are not well suited to this type of usage. Nor polymorphism, abstraction, etc.
That depends, probably a class would be fine in this case. Hope below points help you to decide.
Use of structure in following condition is desirable.
When you have small data structure
Data Structure does not require to extent the functionality.
When you want to perform faster operation on data structure. (As structure are stored on stack, operation performed on it are faster.)
Use of class in following condition is desirable.
When you have complex data structure
Data Structure requires to extend functionality.
When you want to optimize memory usage. (As class is stored on heap, they are about to be garbage collected when no reference pointing to an object.)
Look at here for more details.
On a blog entry, Luca Bolognese ponders this idea about structs vs. classes as member fields:
The reason to use a struct is to not
allocate an additional object on the
stack. This allows this solution to be
as 'performant' as simply having coded
the fields on the class itself. Or at
least I think so ...
How accurate is this?
First, doesn't he mean allocate an additional object on the heap?
And, wouldn't using structs marginally decrease allocation time (especially if the class members were lazy-loaded) at the expense of increasing the memory footprint?
Would you recommend this practice of structs over classes in certain situations?
I think he did mean to write heap, he just wrote stack by mistake.
The question of structs or classes comes up quite often. Here's one example. I think it's best to follow this commonly given advice:
MSDN has the answer: Choosing Between Classes and Structures.
Basically, that page gives you a 4-item checklist and says to use a class unless your type meets all of the criteria.
Do not define a structure unless the type has all of the following characteristics:
* It logically represents a single value, similar to primitive types (integer, double, and so on).
* It has an instance size smaller than 16 bytes.
* It is immutable.
* It will not have to be boxed frequently.
Are there times you shouldn't follow this advice? Maybe, but only after you've proved it by profiling.
I was wondering if the enum structure type has a limit on its members. I have this very large list of "variables" that I need to store inside an enum or as constants in a class but I finally decided to store them inside a class, however, I'm being a little bit curious about the limit of members of an enum (if any).
So, do enums have a limit on .Net?
Yes. The number of members with distinct values is limited by the underlying type of enum - by default this is Int32, so you can get that many different members (2^32 - I find it hard that you will reach that limit), but you can explicitly specify the underlying type like this:
enum Foo : byte { /* can have at most 256 members with distinct values */ }
Of course, you can have as many members as you want if they all have the same value:
enum { A, B = A, C = A, ... }
In either case, there is probably some implementation-defined limit in C# compiler, but I would expect it to be MIN(range-of-Int32, free-memory), rather than a hard limit.
Due to a limit in the PE file format, you probably can't exceed some 100,000,000 values. Maybe more, maybe less, but definitely not a problem.
From the C# Language Specification 3.0, 1.10:
An enum type’s storage format and
range of possible values are
determined by its underlying type.
While I'm not 100% sure I would expect Microsoft C# compiler only allowing non-negative enum values, so if the underlying type is an Int32 (it is, by default) then I would expect about 2^31 possible values, but this is an implementation detail as it is not specified. If you need more than that, you're probably doing something wrong.
You could theoretically use int64 as your base type in the enum and get 2^63 possible entries. Others have given you excellent answers on this.
I think there is a second implied question of should you use an enum for something with a huge number of items. This actually directly applies to your project in many ways.
One of the biggest considerations would be long term maintainability. Do you think the company will ever change the list of values you are using? If so will there need to be backward compatibility to previous lists? How significant a problem could this be? In general, the larger the number of members in an enum correlates to a higher probability the list will need to be modified at some future date.
Enums are great for many things. They are clean, quick and simple to implement. They work great with IntelliSense and make the next programmer's job easier, especially if the names are clear, concise and if needed, well documented.
The problem is an enumeration also comes with drawbacks. They can be problematic if they ever need to be changed, especially if the classes using them are being persisted to storage.
In most cases enums are persisted to storage as their underlying values, not as their friendly names.
enum InsuranceClass
{
Home, //value = 0 (int32)
Vehicle, //value = 1 (int32)
Life, //value = 2 (int32)
Health //value = 3 (int32)
}
In this example the value InsuranceClass.Life would get persisted as a number 2.
If another programmer makes a small change to the system and adds Pet to the enum like this;
enum InsuranceClass
{
Home, //value = 0 (int32)
Vehicle, //value = 1 (int32)
Pet, //value = 2 (int32)
Life, //value = 3 (int32)
Health //value = 4 (int32)
}
All of the data coming out of the storage will now show the Life policies as Pet policies. This is an extremely easy mistake to make and can introduce bugs that are difficult to track down.
The second major issue with enums is that every change of the data will require you to rebuild and redeploy your program. This can cause varying degrees of pain. On a web server that may not be a big issue, but if this is an app used on 5000 desktop systems you have an entirely different cost to redeploy your minor list change.
If your list is likely to change periodically you should really consider a system that stores that list in some other form, most likely outside your code. Databases were specifically designed for this scenario or even a simple config file could be used (not the preffered solution). Smart planning for changes can reduce or avoid the problems associated with rebuilding and redeploying your software.
This is not a suggestion to prematurely optimize your system for the possibility of change, but more a suggestion to structure the code so that a likely change in the future doesn't create a major problem. Different situations will require difference decisions.
Here are my rough rules of thumb for the use of enums;
Use them to classify and define other data, but not as data
themselves. To be clearer, I would use InsuranceClass.Life to
determine how the other data in a class should be used, but I would
not make the underlying value of {pseudocode} InsuranceClass.Life = $653.00 and
use the value itself in calculations. Enums are not constants. Doing
this creates confusion.
Use enums when the enum list is unlikely to change. Enums are great
for fundamental concepts but poor for constantly changing ideas.
When you create an enumeration this is a contract with future
programmers that you want to avoid breaking.
If you must change an enum, then have a rule everyone follows that
you add to the end, not the middle. The alternative is that you
define specific values to each enum and never change those. The
point is that you are unlikely to know how others are using your
enumerations underlying values and changing them can cause misery for anyone
else using your code. This is an order of magnitude more important
for any system that persists data.
The corollary to #2 and #3 is to never delete a member of an enum.
There are specific circles of hell for programmers who do this in a codebase used by others.
Hopefully that expanded on the answers in a helpful way.
I like using structs a lot.
So after reading this article, are there any other concerns I should have against using them all the time?
See Also:
When should I use a struct instead of a class?
When to use struct in C#?
You should make the following considerations about structs:
structs should be immutable (mutable structs are not intuitive and unpredictable)
structs always have a default (public parameterless) constructor that cannot be changed
struct size should not exceed 16 bytes
the Equals and GetHashCode methods should be overriden for better performance
implementing the IEquatable<T> interface is recommended
redefining and == and the != operators is also recommended
I almost never define custom structs. There just aren't that many natural value types around, IMO.
In particular, I would think very, very carefully before defining a mutable struct, especially if it mutates via an interface implementation. Mutable structs behave in ways which people don't expect at all, leading to code which is hard to understand.
I think it's worth reading "Choosing Between Classes and Structures" from "Design Guidelines For Developing Class Libraries".
In particular:
Do not define a structure unless the
type has all of the following
characteristics:
It logically represents a single
value, similar to primitive types
(integer, double, and so on).
It has an instance size smaller than
16 bytes.
It is immutable.
It will not have to be boxed frequently.
Do you really develop types with all of those characteristics frequently?
They don't fit into an Object Oriented programming paradigm like classes do. They are good for small data structures, but I use classes for anything beyond that.
I think main purpose of a struct - to keep only variable types. If you keep some classes into struct - you're wrong.
Ask yourself the following questions about the set of data you're modeling with a struct:
Might it ever need to have any
get/set logic?
Might it ever need to store ANY logic
that is endemic to the data?
Might it need to inherit another set
of data?
Might another set of data need to
inherit this one?
I think if you can heartily answer "no" to all these questions, then there's no good reason not to use a struct. I think people use static subclasses in certain situations where a struct would be more than good enough.
A class is a lot simpler to implement correctly than a struct. If you implement a struct incorrectly it can give you some unexpected errors.
A struct should not be larger than 16 bytes, or you lose most of the performance benefits.
A struct is intended to be a value type, representing a single entity of some kind.
A struct should be immutable. That means that you never change one of the properties in a struct. If you want a struct value that is different you create a new value.
Use of structs should be limited to when all you really need is a small data structure. (as you read). I would only really use them for the smallest of datastructures like coordinates, offsets, and sometimes for graphics.
In many ways, you can think of structs in C# as being like scaled - down classes. They are basically the same as classes but designed more for cases where you simply want to group some data together. They
differ from classes in the following ways:
Some things to keep in mind
Structs are value types, not
reference types. This means they are
stored either in the stack or in-
line (if they are part of another
object that is stored on the heap)
and have the same lifetime
re-strictions as the simple data
types.
Structs do not support inheritance.
There are some differences in the
way constructors work for structs.
In particular, the compiler always
supplies a default no - parameter
constructor, which you are not
permitted to replace.