Related
I have a class called "RelativeData" that is used for comparing values through a state machine. I am trying to build a class that takes snapshots of the data at given intervals. The intervals being: StateBegins, StateMachineBegins, and the one I'm having issue with, liveValue.
The challenge im having is the liveValue(s) I wish to track are in a separate class, There is a large list of values I want to add to track with my RelativeData objects, so my class needs to be generic.
the point of this class is to take snapshots of data.
class RelativeData<T>
{
T initialValue;
T stateValue;
T liveValue; //currently not implemented, since i can't store a ref
public void StateMachineActive(T curValue)
{
initialValue = curValue;
}
public void StateUpdated(T curValue)
{
stateValue = curValue;
}
}
ex) a float called "energy" which belongs to a spell. When the state machine activates, it calls StateMachineActive on my list of relativeData, which preferably could internally update using liveValue, instead of having to pass curValue
Current fix)
I have a manager that adds these values to dictionaries of the generic types.
Dictionary<myKey,relativeData<bool>> relativeBoolData
Dictionary<myKey,relativeData<float>> relativeFloatData
& etc...
However to call StateUpdated, i need to pass the current value, which i need to get from a large switch case using myKey. Doable, but back in C++ days I could just store a T*. Can't turn on unsafe mode since Unity doesn't seem to allow it. I could have the actual values just stored in there, but then everytime I want to get the currentValue (which happens ALOT more often than getting a relative value) everywhere throughout the code, it would increase complexity(be more proc heavy). At least I assume.
Question:
1) Can I store a pointer to a Icomparable type? Can I have liveValue point to a valueType/Primitive data type (ie int, long, enum) elsewhere, like I could in C++ with T*. I know I can pass using "ref" but I can't seem to store it.
2) Should I just store the actual values in there instead, and have everything be retreived through a two tier switch case (First to know which dict to call, the float, bool... and then to retrive the value) would that not increase runtime too heavily? The non-relative values: energy, stability, etc, are used continuously in spells for internal calculations. The relative only used for state machine. (may have 2~60 spells active at once)
3) Is this just a bad pattern, is there a better pattern that I am just not seeing, a better way to take snapshots of generic data?
4) I know arrays are by ref, but that would mean my original data would all have to become arrays right?
5) Should I just leave it the way it is. It works, just a tad messier and slower.
all of them are IComparable: ints, floats, bools, enums..
You can do one of the following:
Create a wrapper class for the values and keep a reference on the wrapper.
public class Wrapper<T>
{
public T Value { get; set; }
}
Store the values in an array and remember the indexes instead of the values themselves.
Store the values in a dictionary and remember their keys instead of the values themselves.
Store an accessor delegate (Func<T>). Note: Lambda expressions automatically keep a reference on the context in which they were first declared. See The Beauty of Closures (by Jon Skeet).
This question already has answers here:
When should I use a struct rather than a class in C#?
(31 answers)
Closed 7 years ago.
C# question.
Say I have a customers class that has a bunch of props for storing string only data such as name postal data and phone numbers.
I don't use this entity for ORM as I'm only adding it to some type of collection for use during app life cycle.
Additionally I don't need to add any entity specific methods to it or persist the data to xml or database, or even to a webservice.
Is it better to make this a struct rather than a class? or no benefit?
Also side question, should I make the collection Customers, a list structure?
Be harsh, please critique.. :)
struct customer
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
struct Customers<List>
{
private customer cust;
public customer Cust
{
get { return cust; }
set { cust = value; }
}
}
I can't see any value in making the customer a struct. The string fields will all be reference types, so you might as well make the whole thing a reference type (ie. class).
I'd be inclined to use one of the built-in collection types rather than create my on type for Customers. Something like:
List<Customer> Customers = new List<Customer>();
I suppose you could look at When to use struct in C#?
Unless you have identified specific reasons for using a struct, use a class.
Update: due to #Dmitry Lobanov: Eric Lippert's post: The Truth About Value Types
Structs vs. Classes
Structs may seem similar to classes,
but there are important differences
that you should be aware of. First of
all, classes are reference types and
structs are value types. By using
structs, you can create objects that
behave like the built-in types and
enjoy their benefits as well.
Heap or Stack?
When you call the New operator on a class, it will be
allocated on the heap. However, when
you instantiate a struct, it can be
created on the stack. This will yield
performance gains. Also, you will not
be dealing with references to an
instance of a struct as you would with
classes. You will be working directly
with the struct instance. Because of
this, when passing a struct to a
method, it's passed by value instead
of as a reference.
Ref.
For what it's worth, I would never use structs because I so very rarely have a need to provide a data only structure that doesn't have some sort of associated behaviour (validators, formatters, etc...).
The one thing that I do like about the basic concept of a "struct" is that it represents a storage system at it's most basic, and therefore should avoid the need to write all those pernickity custom getters and setters and all that sort of stuff... but then again, we now have those lovely auto-properties which effectively achieve the same result from purely a coding perspective, and while the YAGNI nazi in me might say to use the struct because it is meant to be simple, the realist in me knows that I will inevitably want to change the struct to a class anyway, so why not simply implement the class from the beginning and be done with the matter! ;-)
As for the argument of performance, and other benefits... ask yourself the question "does this really matter". If you're writing a serious real-time system... perhaps you want to be using another tool. If you're simply passing around some data, you've likely got oodles of processing croutons at your disposal, and your killer algorithm might not really need to worry about the nano-second difference it's going to make.
Personally I use structs everywhere I need to store information, as long as it will not cause obvious performance issues. In most projects this is never, since the data is either directly mappable to an existing type or is larger than a reference (affecting the invariable LINQ queries and other manipulation). I find that structs are only viable when I can stick the data in an array and leave it there (modifying the variables directly in the array), the struct is rarely used, or the amount of data in the struct is less than 64 bits (ignoring struct overhead).
As it was explained to me, structs should be used only to store data and translate it from one form to another (ToString or ToArray converters).
Also, structs are more restrictive than classes with the primary differences:
Structs are value types while classes are reference types. This means the whole struct instance is copied when it is assigned while only the memory address of a class instance is copied. Since most programs are 32bit or 64bit it is usually recommended to limit the size of the struct to prevent performance issues related to copying struct instances as compared to class instanceses. While this can be overcome by putting the structs in an array, this moves the structs to the heap (instead of stack). Also, using generics like List always returns a copy of the instance, since they use methods to access the values. See also the Struct Instances vs. Class Instances section in Objects (C# Programming Guide)
Structs can be instantiated on the stack, while classes are always instantiated on the heap. This is controlled by the compiler and does not affect coding, though it may have a small performance benefit (which is rarely ever detectable).
Within a struct declaration, fields cannot be initialized unless they are declared as const or static.
A struct cannot declare a default constructor (a constructor without parameters) or a destructor.
Unlike classes, structs can be instantiated without using a new operator.
A struct cannot inherit from another struct or class, and it cannot be the base of a class.
All structs inherit directly from System.ValueType, which inherits from System.Object while classes inherit from System.Object.
A struct cannot be null (use the generic Nullable struct).
I know something about struct type. But I can't understand: what is it for? when have I use it? Classes, simple value-types and enums - that's all that I need.
Any suggestions?
UPD: PLEASE! Don't tell me that struct is in the stack (I know this :). What struct is for?
You choose a struct if you want value-type semantics. You choose a class if you want reference-type semantics. All other concerns are secondary to this one.
MSDN provdies a guide : Choosing Between Classes and Structures:
Consider defining a structure instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
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.
Things that should be a struct (because they are values):
struct Color
struct Point
struct Rectangle
struct GLVertex (contains location, color, normal and texcoord)
struct DateTime
Things that should be a class (because they are things to which you refer):
class RandomGenerator
class Socket
class Thread
class Window
Why?
Consider the following code.
class Button
{
public Point Location { get; set; }
}
class Program
{
public static void Main()
{
var button = Util.GetButtonFromSomewhere();
var location = button.Location;
Util.DrawText("one", location);
location.Y += 50;
Util.DrawText("two", location);
location.Y += 50;
Util.DrawText("three", location);
}
}
This will draw 3 text labels, vertically aligned. But if Point is a class, this will also move the button, which is really unexpected: var location = button.Location feels like it should copy a value, and not a reference! In other words, we think of Point as a value type and not a reference type. "value" here is used in the mathematical sense of value. Consider the number 5, it's an abstract object "somewhere out there", you just "refer" to it. Similarly, a Point simply is. It doesn't reside anywhere, we can't change it. Therefore we choose to make it a struct, so it has the semantics users expect.
On the other hand, we could have class Button { public Window Parent { get; set; } }. Here, Parent is an entity, so we represent it with a reference type - Window. It may make sense to use code like myButton.Parent.Redraw();. So Window should be a class.
So far so good. But all this probably sounds too vague to you. How do you really decide if something "feels" like a reference or a value? My rule of thumb is simple:
What should Foo a = b; a.Mutate(); do?
If it seems like it should leave b unchanged, make Foo a struct.
Otherwise make it a class.
Use the principle of least surprise here.
Simple value types are best implemented via a struct.
Struct Usage Guidelines
It is recommended that you use a
struct for types that meet any of the
following criteria:
* Act like primitive types.
* Have an instance size under 16 bytes.
* Are immutable.
* Value semantics are desirable.
You must also understand that a class instance is allocated on the heap.
A struct -is a vallue type- and is allocated on the stack.
First you must understand the difference between value-type and reference type. I will assume since you said to skip that part that you understand what it is.
Struct is a value-type and you get all of the privileges that you would get working with a value-type.
Structs are passed around by value. When you do something like
DateTime time = new DateTime();
DateTime newTime = time;
// you are not referencing time
// instead you have created a new instance
Structs are NOT lightweight classes they may have many methods, just look at DateTime struct.
Structs maybe lighter in performance, but not all the time. Consider passing a large struct to a method. Because structs are value-types each time you pass one into a method a new instance of the struct is created, hence copying the struct each time. If you have a fairly large struct this will be a much larger performance hit.
You may have to occasionally box and unbox structs, since they are value types.
In short, use a struct to represent an atomic value in memory.
Youcan use structs when you want a "class" with value (rather than reference) semantics.
structs are for objects that represent something whose identity is defined by the values stored in it's properties rather than by an Id or key. These are called "Value types" as opposed tyo objects called "Entity Types", whose identity persists over time and is not dependant on the values of the properties of the object.
As an example, a Person class (an Entity) has an identity that persists from one session to another, even from year to year, in spite of how the Person's address, phone number, employer, etc might change from one instance to another. If you inadvertently have two instances of a Person class in memory at the same time, which represent the same individual/entity, then it is important that they have the same values for their properties.
A CalendarMonth object otoh, (a value type) only has identity defined by the value which specifies which calendar month it is... no matter how many instances of "March 2009" you might be using, they are all interchangeable and equivilent. Another example might be an object representing a FiscalYear designation in a tax program. A great example is an address object. (Not talking here about the asociation of an address with a person or a business, or any other entity, but just the address itself). Changing just about any property of an address makes it a different address. Once you create an address object in memory, it is equivilent and interchangeable with every other address object that has the same properties. This is why these value types should generally be immutable. When you need one, create a new one with the property value(s) you need, and throw it away when you're done using it.
If you don't know why you need it, you probably don't.
struct is a value type rather than a reference type. If you don't know what that means, then you probably aren't going to need it.
Example: Say you want a data type to represent Coordinates at X Y Z. You don't really need any functionality, only three variables. A struct would be good for this, a class may be overkill.
In reality, I think struct is an legacy from C. I do not think we MUST use it in any condition. Perhaps sometime you feel that leaving something on stack rather than on heap is more efficient; but as Java/C# never takes efficient as its first stand, so just neglect it:) That's my opinion.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
There are any number of questions here on SO dealing with the differences between Structs and Classes in C#, and when to use one or the other. (The one sentence answer: use structs if you need value semantics.) There are plenty of guidelines out there about how to choose one or the other, most of which boil down to: use a class unless you meet these specific requirements, then use a struct.
This all makes sense to me.
However, I can't seem to find any real-life examples of people using structs in a system. I'm (semi-)new to C#, and I'm having trouble imagining a concrete situation where structs are really the right choice (at least, I haven't run into one yet.)
So, I turn to the SO world-brain. What are some cases where you actually used a struct in a system where a class wouldn't have worked?
Well a class would still work for it, but an example I could think of is something like a Point. Assuming it is an x and y value, you could use a struct.
struct Point {
int x;
int y;
}
In my mind, I would rather have a more simple representation of a pair of integers than to define a use a class with instantiations when the actual entity does not really have much(or any) behavior.
I used a struct to represent a Geolocation
struct LatLng
{
public decimal Lattitude
{
get;
set;
}
public decimal Longitude
{
get;
set;
}
}
this represents a single entity, for instance I can add 2 LatLng's together or perform other operations on this single entity.
MSDN-struct
The struct type is suitable for
representing lightweight objects such
as Point, Rectangle, and Color.
Although it is possible to represent a
point as a class, a struct is more
efficient in some scenarios. For
example, if you declare an array of
1000 Point objects, you will allocate
additional memory for referencing each
object. In this case, the struct is
less expensive.
Also if you look at primitive types Int32,decimal,double..etc you will notice they are all structs, which allows them to be value types whilst allowing them to implement certain crucial interfaces.
Structs are also typically used in graphics/rendering systems. There are many benefits to making points/vectors structs.
Rico Mariani posted an excellent quiz on value based programming. He discussed many reasons to prefer structs in specific situations, and explained it in detail in his quiz results post.
A Money struct is probably one of the most common, however Phone number or Address are also common.
public struct Money
{
public string Currency { get; set; }
public double Amount { get; set; }
}
public struct PhoneNumber
{
public int Extension { get; set; }
public int RegionCode { get; set; }
//... etc.
}
public struct FullName
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
Keep in mind though that in .NET your structs should not be larger in memory footprint than 16 Bytes, because if they get bigger the CLR has to allocate additional memory.
Also because structs 'live' on the stack (and not the heap as reference types do) you might consider using structs if you need to instantiate a lot of the same types of objects.
The quintessential example is the frameworks nullable types, such as int?. These use structs so they retain the value semantics of an int, yet providing a way to make them null without boxing and turning them into reference types.
You would use a struct when you don't want to pass something by reference. Suppose you have a collection of data, or an object that you wish to pass by value (ie, anything you pass it to is working with its own unique copy, not a reference to the original version) then a struct is the right type to use.
They provide a default implementation for Object.GetHashCode(), so you might want to use a struct instead of a class when the object is a simple collection of non-reference types that you want to use as keys to a dictionary.
They are also useful for PInvoke/interop or low-level networking scenarios where you want precise control over the binary layout of a data structure. (go to www.pinvoke.net for lots of interop code that requires structs)
But really, I never use them myself. Don't sweat not using them.
Basically I try to NOT use them. I find they confuse other developers on the team and thus are not worth the effort. I have only found one case to use it, a custom Enum-like type we use a code generator to produce from XML.
The key for me is to define if I want to keep reference to the same object.
Which makes sence when struct is part of another entity, but does entity itself.
In the example above with LatLong that makes perfect sence, for example. You need to copy values from one object to another, not keep referensing the same object.
I often use structs to represent a domain model value type that might be represented as an enum, but needs an arbitrary unlimited number of discrete values, or I want it to have additional behavior (methods) that you cannot add to an enum... For example, in a recent project many data elements were associated with a specific calendar Month rather than with a date. So I created a CalendarMonth struct that had methods:
static CalendarMonth Parse(DateTime inValue);
static CalendarMonth Parse(string inValue);
and TryParse( ) method,
static bool TryParse(string inValue, out CalendarMonth outVal);
And Properties
int Month { get; set; }
int Year { get; set; }
DateTime StartMonthLocal { get; set; }
DateTime StartMonthUTC{ get; set; }
DateTime EndMonthLocal { get; set; }
DateTime EndMonthUTC { get; set; }
etc.
im not usually concerned with 'data-density' in my business apps. I will typically always use a class unless I specifically want value semantics
this means that i am forseeing a situation where i want to compare two of these things and i want them to show up as the same if they have the same value. With classes this is actually more work because i need to override ==, !=, Equals, and GetHashcode, which even if resharper does it for me, is extra needless code.
So in my mind, always use classes unless you know that you want these things to be compared by value(in this case component value)
So I take it you've never used DateTime (a struct).
I can't believe no one has mentioned XNA: in XNA, almost everything is a struct. So when you do
Matrix rotation = Matrix.CreateRotationZ(Math.PiOver2);
You are really creating a value-type.
This is because, unlike in applications programming, a stall of a few milliseconds while the garbage collector runs is not acceptable (we only get 16.6 ms to render the entire frame!), so we have to avoid allocations as much as possible so the GC doesn't have to run as much.
This is especially true on the XBox 360, where the GC is nowhere near the quality it is on the PC - even an average of one allocation per frame can kill performance!
I have been working in financial institutions where large scale caching and latency requirements was achieved using structs. Basically structs can spare the garbage collector of A LOT of work.
See these examples:
http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/
http://00sharp.wordpress.com/2013/07/04/a-case-for-the-structpart-2/
Basically, I use Structs for modeling geometric and mathematical data, or when I want a Value-based data-structure.
The only time I've ever used a struct was when I was building a Fraction struct:
public struct Fraction
{
public int Numerator {get;set;}
public int Denominator {get; set;}
//it then had a bunch of Fraction methods like Reduce, Add, Subtract etc...
}
I felt that it represents a value, just like the built in value types, and therefore coding against it would feel more natural if it behaved like a value type.
I think the .Net Framework is quite real life. See the list under "Structures":
System Namespace
In some performance-critical situations, a struct (a value type and thus allocated from the stack) can be better than a class (a reference type and thus allocated from the heap). Joe Duffy's blog post "A single-word reader/writer spin lock" shows a real-life application of this.
One I've created in the past is StorageCapacity. It represented 0 bytes to N exabytes (could have gone higher to the yottabyte, but exa seemed enough at the time). The struct made sense since I worked for a storage management company. You would think it was fairly simple: a struct with a StorageUnit (enum) and a Quantity (I used decimal). But when you add in conversions, operators, and classes to support formatting, parsing, etc. it adds up.
The abstraction was useful to enable you to take any StorageCapacity and represent it as bytes, kilobytes, etc. without having to multiply or divide by 1024 many times.
I have given my reasons for using structs already elsewhere (When to use struct in C#), and I have used structs for these reasons in real-life projects:
I would choose to use structs for performance reasons if I needed to store a large number of the same item type in an array, which may happen in image processing.
One needs to use structs for passing structured data between C# and C++.
Unless I have a very good reason to use them I try to avoid them.
I know that some people like to use them for implementing value semantics but I find that this behavior is so different from the "normal" assignment behavior of classes (in C#) that one finds oneself running into difficult to trace bugs because one did not remember that the object one was assigning from or to had this behavior because it was implemented as a struct instead of a class. (It has happened to me more than once, so I give this warning since I actually have been burned by the injudicuous use of C# structs.)
I'm not sure how much use this is, but I discovered today that whilst you cannot have instance field intializers in structs, you can in classes.
Hence the following code will give compilation errors, but if you change the "struct" to "class" it compiles.
public struct ServiceType
{
public bool backEnd { get; set; }
public bool frontEnd { get; set; }
public string[] backEndServices = { "Service1", "Service2" };
public string[] frontEndServices = { "Service3", "Service4" };
}
A struct in C# is at its heart nothing more nor less than a bunch of variables stuck together with duct tape. If one wants each variable of a particular type to represent a bunch of independent but related variables (such as the coordinates of a point) stuck together with duct tape, it's often better to use an exposed-field struct than a class, regardless of whether "bunch" means two or twenty. Note that although Microsoft's struct-versus-class advice is fine for data types which encapsulate a single value, it should be considered inapplicable for types whose purpose is to encapsulate independent but related values. The greater the extent to which the variables are independent, the greater the advantages of using an exposed-field struct.
If one wishes to use a class to encapsulate a bunch of independent variables, there are two ways one can do it, neither of which is terribly convenient. One may use an immutable class, in which case any non-null storage location of that class type will encapsulate the values held by the instance identified thereby, and one storage location may be copied to another to make the new one encapsulate those same values. Unfortunately, changing one of the values encapsulated by a storage location will generally require constructing a new instance which is just like the old one except with that value changed. For example, if one has a variable pt of type Immutable3dPoint and one wished to increase pt.X by one, one would have to do something like: pt = new Immutable3dPoint(pt.X+1, pt.Y, pt.Z); Perhaps tolerable if the type only encapsulates three values, but pretty annoying if there very many.
The other class-based approach is to use a mutable class; this generally requires that one ensure that every storage location of the class type holds the only reference anywhere in the universe to an instance of that class. When a storage location is created, one must construct a new instance and store a reference there. If one wishes to copy the values from storage location P to storage location Q, to another, one must copy all the fields or properties from one instance to the other (perhaps by having the type implement a CopyFrom method, and saying Q.CopyFrom(P);. Note that if one instead says Q=P; that may seem to work, but future attempts to modify P will also modify Q and vice versa. Mutable classes may work, and they can at times be efficient, but it's very easy to mess things up.
Exposed-field structures combine the convenient value-copy semantics of immutable classes with the convenient piecewise modifications allowed by mutable classes. Large structures are slower to copy than are references to immutable objects, but the cost of modifying part of an exposed-field structure depends only upon the extent of the modification, rather than upon the overall structure size. By contrast, the cost of changing one piece of data encapsulated in an immutable class type will be proportional to the total class size.
How do you choose between implementing a value object (the canonical example being an address) as an immutable object or a struct?
Are there performance, semantic or any other benefits of choosing one over the other?
There are a few things to consider:
A struct is allocated on the stack (usually). It is a value type, so passing the data around across methods can be costly if it is too large.
A class is allocated on the heap. It is a reference type, so passing the object around through methods is not as costly.
Generally, I use structs for immutable objects that are not very large. I only use them when there is a limited amount of data being held in them or I want immutability. An example is the DateTime struct. I like to think that if my object is not as lightweight as something like a DateTime, it is probably not worth being used as a struct. Also, if my object makes no sense being passed around as a value type (also like DateTime), then it may not be useful to use as a struct. Immutability is key here though. Also, I want to stress that structs are not immutable by default. You have to make them immutable by design.
In 99% of situations I encounter, a class is the proper thing to use. I find myself not needing immutable classes very often. It's more natural for me to think of classes as mutable in most cases.
How do you choose between implementing a value object (the canonical example being an address) as an immutable object or a struct?
I think your options are wrong. Immutable object and struct are not opposites, nor are they the only options. Rather, you've got four options:
Class
mutable
immutable
Struct
mutable
immutable
I argue that in .NET, the default choice should be a mutable class to represent logic and an immutable class to represent an entity. I actually tend to choose immutable classes even for logic implementations, if at all feasible. Structs should be reserved for small types that emulate value semantics, e.g. a custom Date type, a Complex number type similar entities. The emphasis here is on small since you don't want to copy large blobs of data, and indirection through references is actually cheap (so we don't gain much by using structs). I tend to make structs always immutable (I can't think of a single exception at the moment). Since this best fits the semantics of the intrinsic value types I find it a good rule to follow.
I like to use a thought experiment:
Does this object make sense when only an empty constructor is called?
Edit at Richard E's request
A good use of struct is to wrap primitives and scope them to valid ranges.
For example, probability has a valid range of 0-1. Using a decimal to represent this everywhere is prone to error and requires validation at every point of usage.
Instead, you can wrap a primitive with validation and other useful operations. This passes the thought experiment because most primitives have a natural 0 state.
Here is an example usage of struct to represent probability:
public struct Probability : IEquatable<Probability>, IComparable<Probability>
{
public static bool operator ==(Probability x, Probability y)
{
return x.Equals(y);
}
public static bool operator !=(Probability x, Probability y)
{
return !(x == y);
}
public static bool operator >(Probability x, Probability y)
{
return x.CompareTo(y) > 0;
}
public static bool operator <(Probability x, Probability y)
{
return x.CompareTo(y) < 0;
}
public static Probability operator +(Probability x, Probability y)
{
return new Probability(x._value + y._value);
}
public static Probability operator -(Probability x, Probability y)
{
return new Probability(x._value - y._value);
}
private decimal _value;
public Probability(decimal value) : this()
{
if(value < 0 || value > 1)
{
throw new ArgumentOutOfRangeException("value");
}
_value = value;
}
public override bool Equals(object obj)
{
return obj is Probability && Equals((Probability) obj);
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public override string ToString()
{
return (_value * 100).ToString() + "%";
}
public bool Equals(Probability other)
{
return other._value.Equals(_value);
}
public int CompareTo(Probability other)
{
return _value.CompareTo(other._value);
}
public decimal ToDouble()
{
return _value;
}
public decimal WeightOutcome(double outcome)
{
return _value * outcome;
}
}
Factors: construction, memory requirements, boxing.
Normally, the constructor restrictions for structs - no explicit parameterless constructors, no base construction - decides if a struct should be used at all. E.g. if the parameterless constructor should not initialize members to default values, use an immutable object.
If you still have the choice between the two, decide on memory requirements. Small items should be stored in structs especially if you expect many instances.
That benefit is lost when the instances get boxed (e.g. captured for an anonymous function or stored in a non-generic container) - you even start to pay extra for the boxing.
What is "small", what is "many"?
The overhead for an object is (IIRC) 8 bytes on a 32 bit system. Note that with a few hundred of instances, this may already decide whether or not an inner loop runs fully in cache, or invokes GC's. If you expect tens of thousands of instances, this may be the difference between run vs. crawl.
From that POV, using structs is NOT a premature optimization.
So, as rules of thumb:
If most instances would get boxed, use immutable objects.
Otherwise, for small objects, use an immutable object only if struct construction would lead to an awkward interface and you expect not more than thousands of instances.
I actually don't recommend using .NET structs for Value Object implementation. There're two reasons:
Structs don't support inheritance
ORMs don't handle mapping to structs well
Here I describe this topic in detail: Value Objects explained
In today's world (I'm thinking C# 3.5) I do not see a need for structs (EDIT: Apart from in some niche scenarios).
The pro-struct arguments appear to be mostly based around perceived performance benefits. I would like to see some benchmarks (that replicate a real-world scenario) that illustrate this.
The notion of using a struct for "lightweight" data structures seems way too subjective for my liking. When does data cease to be lightweight? Also, when adding functionality to code that uses a struct, when would you decide to change that type to a class?
Personally, I cannot recall the last time I used a struct in C#.
Edit
I suggest that the use of a struct in C# for performance reasons is a clear case of Premature Optimization*
* unless the application has been performance profiled and the use of a class has been identified as a performance bottleneck
Edit 2
MSDN States:
The struct type is suitable for
representing lightweight objects such
as Point, Rectangle, and Color.
Although it is possible to represent a
point as a class, a struct is more
efficient in some scenarios. For
example, if you declare an array of
1000 Point objects, you will allocate
additional memory for referencing each
object. In this case, the struct is
less expensive.
Unless you need reference type
semantics, a class that is smaller
than 16 bytes may be more efficiently
handled by the system as a struct.
In general, I would not recommend structs for business objects. While you MIGHT gain a small amount of performance by heading this direction, as you are running on the stack, you end up limiting yourself in some ways and the default constructor can be a problem in some instances.
I would state this is even more imperative when you have software that is released to the public.
Structs are fine for simple types, which is why you see Microsoft using structs for most of the data types. In like manner, structs are fine for objects that make sense on the stack. The Point struct, mentioned in one of the answers, is a fine example.
How do I decide? I generally default to object and if it seems to be something that would benefit from being a struct, which as a rule would be a rather simple object that only contains simple types implemented as structs, then I will think it through and determine if it makes sense.
You mention an address as your example. Let's examine one, as a class.
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
Think through this object as a struct. In the consideration, consider the types included inside this address "struct", if you coded it that way. Do you see anything that might not work out the way you want? Consider the potential performance benefit (ie, is there one)?
What is the cost of copying instances if passed by value.
If high, then immutable reference (class) type, otherwise value (struct) type.
As a rule of thumb a struct size should not exceed 16 bytes, otherwise passing it between methods may become more expensive that passing object references, which are just 4 bytes (on a 32-bit machine) long.
Another concern is a default constructor. A struct always has a default (parameterless and public) constructor, otherwise the statements like
T[] array = new T[10]; // array with 10 values
would not work.
Additionally it's courteous for structs to overwrite the == and the != operators and to implement the IEquatable<T> interface.
From an object modeling perspective, I appreciate structs because they let me use the compiler to declare certain parameters and fields as non-nullable. Of course, without special constructor semantics (like in Spec#), this is only applicable to types that have a natural 'zero' value. (Hence Bryan Watt's 'though experiment' answer.)
Structs are strictly for advances users ( along with out and ref) .
Yes structs can give great performance when using ref but you have to see what memory they are using. Who controls the memory etc.
If your not using ref and outs with structs they are not worth it , if you are expect some nasty bugs :-)