HomeSearch

C# struct Examples

Test structs. Understand that structs are value types and types like int are structs.
Struct. A struct stores its data in its type. It is not allocated separately on the managed heap. Structs often reside on the evaluation stack.
Struct details. Every program uses simple structs. All value types (int, bool, char) are structs. We rarely benefit from creating custom structs.Int, uintBoolChar
First example. A struct uses syntax similar to a class. It is a type definition. We describe a struct called Simple: this struct stores 3 values—an int, a bool and a double value.

Step 1: The struct is created on the stack. No "new" keyword is used. It is used like a value type such as int.

Step 2: We can access a field from a struct, in the same way that we can access a class field.

Class

Info: The struct has the composite name "Program.Simple": it is nested within the Program class.

C# program that declares struct using System; class Program { struct Simple { public int Position; public bool Exists; public double LastValue; }; static void Main() { // Step 1: create struct on stack. Simple s; s.Position = 1; s.Exists = false; s.LastValue = 5.5; // Step 2: write struct field. Console.WriteLine(s.Position); } } Output 1
DateTime. DateTime is a value that indicates a point in time. This is a struct. Positions, coordinates and points can sometimes benefit from being structs.DateTime

Step 1: We see that DateTime is a struct. We create a DateTime and then copy it into a separate DateTime variable.

Step 2: We print the values of the DateTime and its copy—the copy has all the same internal data as the original, but is separate.

Step 3: We change the original DateTime. Here the copy remains the same—it is kept separate.

C# program that uses DateTime struct using System; class Program { static void Main() { // Step 1: create Date Time and copy it. DateTime date = new DateTime(2000, 1, 1); DateTime dateCopy = date; // Step 2: show struct values. Console.WriteLine(date); Console.WriteLine(dateCopy); // Step 3: see that copy is not modified. date = DateTime.MinValue; Console.WriteLine(dateCopy); } } Output 1/1/2000 12:00:00 AM 1/1/2000 12:00:00 AM 1/1/2000 12:00:00 AM
Property. Next we see an example of using properties with the struct type. Remember that your struct cannot inherit like classes or have complex constructors.

Tip: You can provide properties for the struct that simplify access to its data.

Property
C# program that uses property on struct using System; class Program { static void Main() { // Initialize to 0. S st = new S(); st.X = 5; Console.WriteLine(st.X); } struct S { int _x; public int X { get { return _x; } set { if (value < 10) { _x = value; } } } }; } Output 5
Class. You can't easily change many classes (ones that inherit or implement interfaces) to structs. For simple classes, we can specify a struct to test performance.

Part 1: We create a class instance by using the new keyword. We can then access its public fields X and Y.

New

Part 2: We create a struct. We don't have to instantiate a struct with the new keyword. We can directly access it.

Info: You cannot use a custom default constructor on structs, as when they are constructed, all fields are assigned to zero.

C# program that uses class and struct using System; class Program { class C { public int X; public int Y; } struct CStruct { public int X; public int Y; } static void Main() { // Part 1: use class. C local = new C(); local.X = 1; local.Y = 2; Console.WriteLine("CLASS X: {0}", local.X); // Part 2: use struct. CStruct localStruct; localStruct.X = 1; localStruct.Y = 2; Console.WriteLine("STRUCT X: {0}", localStruct.X); } } Output CLASS X: 1 STRUCT X: 1
Structs, ASP.NET. Consider a website that records referrer data. Each struct here could store string fields and a DateTime field.

And: Because DateTime itself is a struct, it will be stored directly in the struct allocation on the stack.

Thus: In a struct with two strings and a DateTime, the struct will hold two references and one value together.

Example: We replaced the class with a struct. This should improve performance by about two times and reduce memory.

C# program that uses struct in website using System; using System.Collections.Generic; class Program { static void Main() { var _d = new Dictionary<string, ReferrerInfo>(); // New struct: ReferrerInfo i; i.OriginalString = "cat"; i.Target = "mat"; i.Time = DateTime.Now; _d.Add("info", i); } /// <summary> /// Contains information about referrers. /// </summary> struct ReferrerInfo { public string OriginalString; // Reference. public string Target; // Reference. public DateTime Time; // Value. }; }
Structs, offsets. In a database system, file blobs are stored in large files together. We can store their offsets instructs that have 2 members—ints storing positions.

And: Structs were ideal here. There were over 500 instances of the object. And they only had two fields (both value types).

KeyValuePair: The .NET Framework provides the KeyValuePair struct for storing a pair. It is used internally in the Dictionary.

KeyValuePair

Also: It is worthwhile to use structs for graphics. When using graphics contexts, we use structs for points and coordinates.

C# program that uses Dictionary of structs using System.Collections.Generic; class Program { static void Main() { // Stores Dictionary of structs. var _d = new Dictionary<string, FileData>(); FileData f; f.Start = 1000; f.Length = 200; _d.Add("key", f); } /// <summary> /// Stores where each blob is stored. /// </summary> struct FileData { public int Start; public int Length; } }
Memory usage. Suppose we have a List of class instances, and a List of structs. The class instances will all be separate objects, but the structs can all be stored together.ListMemory

Info: Using structs, CLRProfiler indicates that the List took 24 bytes and contained one object of 4.0 MB.

Tip: Structs are not stored as separate objects in arrays, but are grouped together. We see that structs consume less memory.

Class version: Size of List: 1 object 512 KB Size of internal array: 100000 objects 3.8 MB Struct version: Size of List: 1 object 24 bytes Size of internal array: 1 object 4.0 MB
Benchmark, allocation. Since they are simpler, structs should be faster to allocate than classes. We time the performance in .NET for each type.Benchmark

Version 1: In this version of the code, we allocate a class in a tight loop and compute the average amount of time required.

Version 2: Here we allocate a struct that has the same fields as the class. Each type has 8 fields.

Result: We see substantial speedups when allocating the structs. For pure allocation speed, structs are faster.

Important: Strings are reference types. Their internal data is not embedded in the struct—it just stores the reference.

C# program that times classes, structs using System; using System.Diagnostics; class AllocateClass { public string A; public string B; public string C; public string D; public int E; public int F; public int G; public int H; } struct AllocateStruct { public string A; public string B; public string C; public string D; public int E; public int F; public int G; public int H; } class Program { const int _max = 10000000; static void Main() { var s1 = Stopwatch.StartNew(); // Version 1: allocate class. for (int i = 0; i < _max; i++) { AllocateClass test = new AllocateClass(); test.E = 10; if (test.E != 10) { return; } } s1.Stop(); var s2 = Stopwatch.StartNew(); // Version 2: allocate struct. for (int i = 0; i < _max; i++) { AllocateStruct test; test.E = 10; if (test.E != 10) { return; } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output 4.28 ns Allocate class 0.98 ns Allocate struct
Notes, value types. Structs are custom value types that store the values in each field together. They do not store referenced data, but can store references.

Tip: Heap allocation is used for the data of arrays and objects. Structs, meanwhile, have all their data stored inline.

Info: With structs you avoid the overhead of objects. This reduces memory pressure. And it (sometimes) improves performance.

Term: The term "value semantics" refers to how a struct has all its data inline, and is not stored in a separate location on the heap.

Usage, small classes. Often in programs we have small classes that serve as collections of related variables stored in memory. Here we require no inheritance or polymorphism.

Tip: These types often make ideal structs. But even here, structs may make things worse (often because of parameter passing).

Stack, heap. Locals are allocated on the stack. This includes ints and object references. When we create an object from a class, it is allocated on the heap. The stack is normally faster.
Parameters. This is important. Structs are copied when you pass them as parameters to methods. Structs can therefore degrade performance when passed to methods.Struct vs. Class
Null. You cannot compare a struct instance to the null literal. If this is confusing, think of structs as ints or bools. You can't set your integer variable to null.

Note: Nullable types are a generic type that can be null. In complex programs these can help simplify code.

Nullable
Strings. You can use string fields in struct types. The struct will not store the string's data. Strings are objects, so the data will be stored externally, where the reference points.

However: Using structs can improve performance with the string reference itself. References are also data.

Pointers, unsafe. The C# language frees us from the complexity of pointers and memory allocation. But understanding pointers is important.

Tip: Pointers, like references, are values that contain the addresses of data. When used correctly, pointers are fast.

But: Their syntax and lack of error checking causes problems. They are harder to use than references.

Fixed buffers: The struct type can be used with fixed buffers as a memory region.

Fixed
ValueType. Values such as integers are stored in structs. The ValueType class is an abstract base class for these values. You can refer to them with a ValueType reference.ValueType
A summary. Structs are an advanced topic. But every developer has used them in value types. Custom structs often degrade performance, so should be typically avoided.
Home
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.