How to calculate how big a struct or class is? - c#

I've been told I should only use structs when they are less than 16 bytes. If bigger, it would be more optimal to use a class.
I was wondering, how do I work that out?
Do I just add up all of the fields that are in the struct?
For example, if this struct
public struct Struct1
{
int int1;
}
Then given it's got one integer and one int is 32 bits, is it then four bytes?
What about if I have lots of methods in this struct though? Would the method add to the size of the struct?

Only non-static variables use up space, methods don't. For example, your struct that you made there is four bytes big, because it is the size of an int.
You can also calculate the size using Marshal.SizeOf(GetType((Struct1)).
Unless you have memory critical applications, or have some special reasons you need a struct, I would suggest always using a class.

Use the built-in sizeof keyword.
EDIT: Nevermind, only available when dealing with unsafe code. (also, only really useful then too)

I would not solely think about the 16bytes limit when deciding whether to use a class or struct. I would look at the semantics first. If you need to create an entity, I would use a class. If you need to create a value type, I would first think of a struct.

Your best bet: When should I use a struct instead of a class?
MSDN has the answer: 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.

Make this analysis, and further, the decision, based on any such conclusion at design-time - not runtime, since you can't change the type definition at that point.
In order for you to work out the sizes, I'll just point you forward to a very interesting article (from 2005 MSDN magazine, but still relevant) which discusses the allocation of objects in the CLR, with reference to sizes, offsets et cetera; this will educate you more than enough to be able to determine what you need and also enable you to research further into what you're still unsure of:
http://msdn.microsoft.com/en-us/magazine/cc163791.aspx

Related

Why is Uri a class and not a struct?

System.Uri seems to be a perfect candidate for being a struct but the good folks at Microsoft decided to make it a class. It is clearly a value object -> there is no sense in having two different instances of "https://stackoverflow.com" and so it has struct-y equality rules. I can't see any setters on the public API either, so it is immutable.
Is there some implementation detail which dictates it must be a class?
A struct would always have a default constructor (where all fields would be initialized to their default values). This could cause issues, for example, with some of the internal fields.
One example is that the existing constructor ensures that m_String can't be null - https://referencesource.microsoft.com/#system/net/system/UriExt.cs,39 . If you made this a struct, you can't easily achieve that in C#. So, everywhere you read from m_String you'd need to add a null check (which is not required if it is a class).
Additionally, as others have pointed out, the docs have other guidance on choosing when to use struct:
✓ CONSIDER defining a struct instead of a class if instances of the
type are small and commonly short-lived or are commonly embedded in
other objects.
X AVOID defining a struct unless the type has all of the following
characteristics:
It logically represents a single value, similar to primitive types
(int, double, etc.).
It has an instance size under 16 bytes.
It is immutable.
It will not have to be boxed frequently.
The 16 byte requirement, in particular, is likely to be problematic for Uri.

C# Limitations of struct. Why are they sealed? [duplicate]

This question already has answers here:
Why are .NET value types sealed?
(4 answers)
Closed 9 years ago.
I am having a bit of an issue grasping the concept of the struct and no one can answer my question.
I know it is "like" an object, you can have methods and fields.
What I do not understand is why they are sealed. Why is there a lack of inheritance and polymorphism
which limits their abilities. Is there really much real world use for a struct, I know they are smaller than
an object, I just cannot find any real examples that help me understand the benefits.
Thanks.
Because a struct is a value; a struct that contains a float is exactly 4 bytes long. There is no object-header that indicates what the concrete type is: the thing that knows the type is the compiler (and the resulting IL) - the type information is not self-contained in the value. So, regular polymorphism cannot work. If you do:
MyType type = new MySubType(); // if this was a struct and if this compiled
then from the compiler's perspective, the type of that is MyType. There is no notion, after the assignment, that this is or ever was a MySubType. Indeed, you can use unsafe code to force the bits of one value-type into another.
Additionally, this same facet of structs means that you would not be able to add fields in sub-types: the size has to be fixed, which makes this impossible.
Basically, if you are thinking in terms of inheritance, you are using structs incorrectly; actually, most times that I see people using structs they are using them incorrectly. structs should represent values (ideally immutable etc).
Is there really much real world use for a struct
Yes; for representing values - a ComplexNumber type for example; and for some highly optimized scenarios where GC is prohibitive, but which only affects a small number of developers. Here's one example of this; another common example is "games", but: switching between class and struct is a much bigger change than changing the keyword. You need to know what you are doing, and why you are doing it.
What you should not do is things like:
// ***BAD CODE: DO NOT DO***
public struct Customer
{ // I don't need inheritance; a struct will be faster and smaller
// yay me, I'm awesome
public int Id;
public string Name;
}
The above is clearly best represented as a class. Also: properties.
I know they are smaller than an object
In some ways, this is not true; for example, most useful structs are larger than a reference - which can be problematic if you are passing super-sized structs around on the stack without thinking what you are doing.
It is simple. It is a value type and all value types are sealed. Though you can inherit it from interface.

Immutable class vs struct

The following are the only ways classes are different from structs in C# (please correct me if I'm wrong):
Class variables are references, while struct variables are values, therefore the entire value of struct is copied in assignments and parameter passes
Class variables are pointers stored on stack that point to the memory on heap, while struct variables are on stored heap as values
Suppose I have an immutable struct, that is struct with fields that cannot be modified once initialized. Each time I pass this struct as a parameter or use in assignments, the value would be copied and stored on stack.
Then suppose I make this immutable struct to be an immutable class. The single instance of this class would be created once, and only the reference to the class would be copied in assignments and parameter passes.
If the object was mutable, the behavior in these two cases would be different: when one would change the object, in the first case the copy of the struct would be modified, while in the second case the original object would be changed. However, in both cases the object is immutable, therefore there is no difference whether this is actually a class or a struct for the user of this object.
Since copying reference is cheaper than copying struct, why would one use an immutable struct?
Also, since mutable structs are evil, it looks like there is no reason to use structs at all.
Where am I wrong?
Since copying reference is cheaper than copying struct, why would one use an immutable struct?
This isn't always true. Copying a reference is going to be 8 bytes on a 64bit OS, which is potentially larger than many structs.
Also note that creation of the class is likely more expensive. Creating a struct is often done completely on the stack (though there are many exceptions), which is very fast. Creating a class requires creating the object handle (for the garbage collector), creating the reference on the stack, and tracking the object's lifetime. This can add GC pressure, which also has a real cost.
That being said, creating a large immutable struct is likely not a good idea, which is part of why the Guidelines for choosing between Classes and Structures recommend always using a class if your struct will be more than 16 bytes, if it will be boxed, and other issues that make the difference smaller.
That being said, I often base my decision more on the intended usage and meaning of the type in question. Value types should be used to refer to a single value (again, refer to guidelines), and often have a semantic meaning and expected usage different than classes. This is often just as important as the performance characteristics when making the choice between class or struct.
Reed's answer is quite good but just to add a few extra points:
please correct me if I'm wrong
You are basically on the right track here. You've made the common error of confusing variables with values. Variables are storage locations; values are stored in variables. And you are flirting with the commonly-stated myth that "value types go on the stack"; rather, variables go on either short-term or long-term storage, because variables are storage locations. Whether a variable goes on short or long term storage depends on its known lifetime, not its type.
But all of that is not particularly relevant to your question, which boils down to asking for a refutation of this syllogism:
Mutable structs are evil.
Reference copying is cheaper than struct copying, so immutable structs are always worse.
Therefore, there is never any use for structs.
We can refute the syllogism in several ways.
First, yes, mutable structs are evil. However, they are sometimes very useful because in some limited scenarios, you can get a performance advantage. I do not recommend this approach unless other reasonable avenues have been exhausted and there is a real performance problem.
Second, reference copying is not necessarily cheaper than struct copying. References are typically implemented as 4 or 8 byte managed pointers (though that is an implementation detail; they could be implemented as opaque handles). Copying a reference-sized struct is neither cheaper nor more expensive than copying a reference-sized reference.
Third, even if reference copying is cheaper than struct copying, references must be dereferenced in order to get at their fields. Dereferencing is not zero cost! Not only does it take machine cycles to dereference a reference, doing so might mess up the processor cache, and that can make future dereferences far more expensive!
Fourth, even if reference copying is cheaper than struct copying, who cares? If that is not the bottleneck that is producing an unacceptable performance cost then which one is faster is completely irrelevant.
Fifth, references are far, far more expensive in memory space than structs are.
Sixth, references add expense because the network of references must be periodically traced by the garbage collector; "blittable" structs may be ignored by the garbage collector entirely. Garbage collection is a large expense.
Seventh, immutable value types cannot be null, unlike reference types. You know that every value is a good value. And as Reed pointed out, in order to get a good value of a reference type you have to run both an allocator and a constructor. That's not cheap.
Eighth, value types represent values, and programs are often about the manipulation of values. It makes sense to "bake in" the metaphors of both "value" and "reference" in a language, regardless of which is "cheaper".
From MSDN;
Classes are reference types and structures are value types. Reference
types are allocated on the heap, and memory management is handled by
the garbage collector. Value types are allocated on the stack or
inline and are deallocated when they go out of scope. In general,
value types are cheaper to allocate and deallocate. However, if they
are used in scenarios that require a significant amount of boxing and
unboxing, they perform poorly as compared to reference types.
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.
So, you should always use a class instead of struct, if your struct will be more than 16 bytes. Also read from http://www.dotnetperls.com/struct
There are two usage cases for structures. Opaque structures are useful for things which could be implemented using immutable classes, but are sufficiently small that even in the best of circumstances there wouldn't be much--if any--benefit to using a class, especially if the frequency with which they are created and discarded is a significant fraction of the frequency with which they will be simply copied. For example, Decimal is a 16-byte struct, so holding a million Decimal values would take 16 megabytes. If it were a class, each reference to a Decimal instance would take 4 or 8 bytes, but each distinct instance would probably take another 20-32 bytes. If one had many large arrays whose elements were copied from a small number of distinct Decimal instances, the class could win out, but in most scenarios one would be more likely to have an array with a million references to a million distinct instances of Decimal, which would mean the struct would win out.
Using structures in this way is generally only good if the guidelines quoted from MSDN apply (though the immutability guideline is mainly a consequence of the fact that there isn't yet any way via which struct methods can indicate that they modify the underlying struct). If any of the last three guidelines don't apply, one is likely better off using an immutable class than a struct. If the first guideline does not apply, however, that means one shouldn't use an opaque struct, but not that one should use a class instead.
In some situations, the purpose of a data type is simply to fasten a group of variables together with duct tape so that their values can be passed around as a unit, but they still remain semantically as distinct variables. For example, a lot of methods may need to pass around groups of three floating-point numbers representing 3d coordinates. If one wants to draw a triangle, it's a lot more convenient to pass three Point3d parameters than nine floating-point numbers. In many cases, the purpose of such types is not to impart any domain-specific behavior, but rather to simply provide a means of passing things around conveniently. In such cases, structures can offer major performance advantages over classes, if one uses them properly. A struct which is supposed to represent three varaibles of type double fastened together with duct tape should simply have three public fields of type double. Such a struct will allow two common operations to be performed efficiently:
Given an instance, take a snapshot of its state so the instance can be modified without disturbing the snapshot
Given an instance which is no longer needed, somehow come up with an instance which is slightly different
Immutable class types allow the first to be performed at fixed cost regardless of the amount of data held by the class, but they are inefficient at the second. The greater the amount of data the variable is supposed to represent, the greater the advantage of immutable class types versus structs when performing the first operation, and the greater the advantage of exposed-field structs when performing the second.
Mutable class types can be efficient in scenarios where the second operation dominates, and the first is needed seldom if ever, but it can be difficult for an object to expose the present values in a mutable class object without exposing the object itself to outside modification.
Note that depending upon usage patterns, large exposed-field structures may be much more efficient than either opaque structures or class types. Structure larger than 17 bytes are often less efficient than smaller ones, but they can still be vastly more efficient than classes. Further, the cost of passing a structure as a ref parameter does not depend upon its size. Large structs are inefficient if one accesses them via properties rather than fields, passes them by value needlessly, etc. but if one is careful to avoid redundant "copy" operations, there are usage patterns where there is no break-even point for classes versus structs--structs will simply perform better.
Some people may recoil in horror at the idea of a type having exposed fields, but I would suggest that a struct such as I describe shouldn't be thought of so much as an entity unto itself, but rather an extension of the things that read or write it. For example:
public struct SlopeAndIntercept
{
public double Slope,Intercept;
}
public SlopeAndIntercept FindLeastSquaresFit() ...
Code which is going to perform a least-squares-fit of a bunch of points will have to do a significant amount of work to find either the slope or Y intercept of the resulting line; finding both would not cost much more. Code which calls the FindLeastSquaresFit method is likely going to want to have the slope in one variable and the intercept in another. If such code does:
var resultLine = FindLeastSquaresFit();
the result will be to effectively create two variables resultLine.Slope and resultLine.Intercept which the method can manipulate as it sees fit. The fields of resultLine don't really belong to SlopeIntercept, nor to FindLeastSquaresFit; they belong to the code that declares resultLine. The situation is little different from if the method were used as:
double Slope, Intercept;
FindLeastSquaresFit(out Slope, out Intercept);
In that context, it would be clear that immediately following the function call, the two variables have the meaning assigned by the method, but that their meaning at any other time will depend upon what else the method does with them. Likewise for the fields of the aforementioned structure.
There are some situations where it may be better to return data using an immutable class rather than a transparent structure. Among other things, using a class will make it easier for future versions of a function that returns a Foo to return something which includes additional information. On the other hand, there are many situations where code is going to expect to deal with a specific set of discrete things, and changing that set of things would fundamentally change what clients have to do with it. For example, if one has a bunch of code that deals with (x,y) points, adding a "z" coordinate is going to require that code to be rewritten, and there's nothing the "point" type can do to mitigate that.

What (if any) are the implications of having an object or a nullable type as a field in a struct

For performance reasons I use structs in several use cases.
If I have an object or a nullable type (another struct but nullable) as a member in the struct, is there an adverse effect on performance. Do I lose the very benefit I am trying to gain?
Edit
I am aware of the size limitations and proper use of structs. Please no more lectures. In performance tests the structs perform faster.
I do not mean to sound abrasive or ungrateful, but how do I make my question any more simple?
Does having a object as a member of a struct impact performance or negate the benefit?
Well, C# is a strange beast when it comes to the performance part of struct vs classes.
Check this link: http://msdn.microsoft.com/en-us/library/y23b5415(VS.71).aspx
According to Microsoft you should use a struct only when the instance size is under 16 bytes. Andrew is right. If you do not pass around a struct, you might see a performance benefit. Value type semantics have a heavy performance (and at time memory, depending on what you are doing) penalty while passing them around.
As far as collections are concerned, if you are using a non-generic collection, the boxing and unboxing of a value-type (struct in this case) will have a higher performance overhead than a reference type (i.e. class). That said, it is also true that structs get allocated faster than classes.
Although struct and class have same syntax, the behavior is vastly different. This can force you to make many errors that might be difficult to trace. For example, like static constructors in a struct would not be called when you call it's public (hidden constructor) or as operator will fail with structs.
Nullable types are themselves are implemented with structs. But they do have a penalty. Even every operation of a Nullable type emit more IL.
Well, in my opinion, struct are well left to be used in types such as DateTime or Guids. If you need an immutable type, use struct otherwise, don't. The performance benefits are not that huge. Similarly even the overhead is not that huge. So at the end of day, it depends on your data you are storing in the struct and also how you are using it.
No, you won't lose the benefit necessarily. One area in which you see a performance benefit from using a struct is when you are creating many objects quickly in a loop and do not need to pass these objects to any other methods. In this case you should be fine but without seeing some code it is impossible to tell.
Personally, I'd be more worried about simply using structs inappropriately; what you have described sounds like an object (class) to me.
In particular, I'd worry about your struct being too big; when you pass a struct around (between variables, between methods, etc) it gets copied. If it is a big fat beast with lots of fields (some of which are themselves beasts) then this copy will take more space on the stack, and more CPU time. Contrast to passing a reference to an object, which takes a constant size / time (width per your x86/x64 architecture).
If we talk about basic nullable types, such as classic "values"; Nullable<T> of course has an overhead; the real questions are:
is it too much
is it more expensive than the check I'd still have to do for a "magic number" etc
In particular, all casts and operators on Nullable<T> get extra code - for example:
int? a = ..., b = ...;
int? c = a + b;
is really more similar to:
int? c = (a.HasValue && b.HasValue) ?
new Nullable<int>(a.GetValueOrDefault() + b.GetValueOrDefault())
: new Nullable<int>();
The only way to see if this is too much is going to be with your own local tests, with your own data. The fact that the data is on a struct in this case is largely moot; the numbers should broadly compare no matter where they are.
Nullable<T> is essentially a tuple of T and bool flag indicating whether it's null or not. Its performance effect is therefore exactly the same: in terms of size, you get that extra bool (plus whatever padding it deems required).
For references to reference types, there are no special implications. It's just whatever the size of an object reference is (which is usually sizeof(IntPtr), though I don't think there's a definite guarantee on that). Of course, GC would also have to trace through those references every now and then, but a reference inside a struct is not in any way special in that regard.
Neither nullable types nor immutable class types will pose a problem within a struct. When using mutable class types, however, one should generally try to stick to one of two approaches:
The state represented by mutable class field or property should be the *identity*, rather than the *mutable charactersitics*, of the mutable object referenced thereby. For example, suppose a struct has a field of type `Car`, which holds a reference to a red car, vehicle ID #24601. Suppose further that someone copies the struct and then paints the vehicle referred to blue. An object reference would be appropriate if, under such circumstances, one would want the structure to hold a reference to a blue car with ID #24601. It would be inappropriate if one would want the structure to still hold a refernce to a red car (which would have to have some other ID, since car ID #24601 is blue).
Code within the struct creates a mutable class instance, performs all mutations that will ever be performed to that instance (possibly copying data from a passed-in instance), and stores it in a private field after all mutations are complete. Once a reference to the instance is stored in a field, the struct must never again mutate that instance, nor expose it to any code which could mutate it.
Note that the two approaches offer very different semantics; one should never have a hard time deciding between them, since in any circumstance where one is appropriate the other would be completely inappropriate. In some circumstances there may be other approaches which would work somewhat better, but in general one should identify whether a struct's state includes the identity or mutable characteristics of any nested mutable classes, and use one of the patterns above as appropriate.

Why do we need struct? (C#)

To use a struct, we need to instantiate the struct and use it just like a class. Then why don't we just create a class in the first place?
A struct is a value type so if you create a copy, it will actually physically copy the data, whereas with a class it will only copy the reference to the data
A major difference between the semantics of class and struct is that structs have value semantics. What is this means is that if you have two variables of the same type, they each have their own copy of the data. Thus if a variable of a given value type is set equal to another (of the same type), operations on one will not affect the other (that is, assignment of value types creates a copy). This is in sharp contrast to reference types.
There are other differences:
Value types are implicitly sealed (it is not possible to derive from a value type).
Value types can not be null.
Value types are given a default constructor that initialzes the value type to its default value.
A variable of a value type is always a value of that type. Contrast this with classes where a variable of type A could refer to a instance of type B if B derives from A.
Because of the difference in semantics, it is inappropriate to refer to structs as "lightweight classes."
All of the reasons I see in other answers are interesting and can be useful, but if you want to read about why they are required (at least by the VM) and why it was a mistake for the JVM to not support them (user-defined value types), read Demystifying Magic: High-level Low-level Programming. As it stands, C# shines in talking about the potential to bring safe, managed code to systems programming. This is also one of the reasons I think the CLI is a superior platform [than the JVM] for mobile computing. A few other reasons are listed in the linked paper.
It's important to note that you'll very rarely, if ever, see an observable performance improvement from using a struct. The garbage collector is extremely fast, and in many cases will actually outperform the structs. When you add in the nuances of them, they're certainly not a first-choice tool. However, when you do need them and have profiler results or system-level constructs to prove it, they get the job done.
Edit: If you wanted an answer of why we need them as opposed to what they do, ^^^
In C#, a struct is a value type, unlike classes which are reference types. This leads to a huge difference in how they are handled, or how they are expected to be used.
You should probably read up on structs from a book. Structs in C# aren't close cousins of class like in C++ or Java.
This is a myth that struct are always created on heap.
Ok it is right that struct is value type and class is reference type. But remember that
1. A Reference Type always goes on the Heap.
2. Value Types go where they were declared.
Now what that second line means is I will explain with below example
Consider the following method
public void DoCalulation()
{
int num;
num=2;
}
Here num is a local variable so it will be created on stack.
Now consider the below example
public class TestClass
{
public int num;
}
public void DoCalulation()
{
TestClass myTestClass = new TestClass ();
myTestClass.num=2;
}
This time num is the num is created on heap.Ya in some cases value types perform more than reference types as they don't require garbage collection.
Also remeber:
The value of a value type is always a value of that type.
The value of a reference type is always a reference.
And you have to think over the issue that if you expect that there will lot be instantiation then that means more heap space yow will deal with ,and more is the work of garbage collector.For that case you can choose structs.
Structs have many different semantics to classes. The differences are many but the primary reasons for their existence are:
They can be explicitly layed out in memmory
this allows certain interop scenarios
They may be allocated on the stack
Making some sorts of high performance code possible in a much simpler fashion
the difference is that a struct is a value-type
I've found them useful in 2 situations
1) Interop - you can specify the memory layout of a struct, so you can guarantee that when you invoke an unmanaged call.
2) Performance - in some (very limited) cases, structs can be faster than classes, In general, this requires structs to be small (I've heard 16 bytes or less) , and not be changed often.
One of the main reasons is that, when used as local variables during a method call, structs are allocated on the stack.
Stack allocation is cheap, but the big difference is that de-allocation is also very cheap. In this situation, the garbage collector doesn't have to track structs -- they're removed when returning from the method that allocated them when the stack frame is popped.
edit - clarified my post re: Jon Skeet's comment.
A struct is a value type (like Int32), whereas a class is a reference type. Structs get created on the stack rather than the heap. Also, when a struct is passed to a method, a copy of the struct is passed, but when a class instance is passed, a reference is passed.
If you need to create your own datatype, say, then a struct is often a better choice than a class as you can use it just like the built-in value types in the .NET framework. There some good struct examples you can read here.

Categories

Resources