Home
C#
struct Examples
Updated Dec 24, 2024
Dot Net Perls
Struct. A C# struct stores its data in its type. It is not allocated separately on the managed heap—instead structs often reside on the evaluation stack.
Every program uses simple structs: all value types (int, bool, char) are structs. We rarely benefit from creating custom structs.
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.
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); } }
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.
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); } }
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
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; } } } }; }
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.
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); } }
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 2 strings and a DateTime, the struct will hold 2 references and one value together.
Detail We replaced the class with a struct. This should improve performance by about 2 times and reduce memory.
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).
Detail We can use the KeyValuePair struct for storing a pair. It is used internally in the Dictionary.
KeyValuePair
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.
List
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.
Size of List: 1 object 512 KB Size of internal array: 100000 objects 3.8 MB
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.
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")); } }
4.28 ns Allocate class 0.98 ns Allocate struct
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
struct Test { int size; } class Program { public static void Main() { var s = new Test(); if (s == null) { } } }
C:\...\Program.cs(11,13): error CS0019: Operator '==' cannot be applied to operands of type 'Test' and '<null>' The build failed. Fix the build errors and run again.
Summary. Structs are an advanced topic, but every C# developer has used them in value types. Custom structs often degrade performance, so should be typically avoided.
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.
This page was last updated on Dec 24, 2024 (new example).
Home
Changes
© 2007-2025 Sam Allen