
Structs have different performance from classes. They are used as parameters in methods—this influences the time required to call a method. We test struct parameters. We decide if this is an effective coding technique.
This C# tutorial is about the memory usage of structs versus classes.
First, here are two type declarations in the C# language. The first declaration is a struct type, which by definition inherits from the System.ValueType object. Internally, the struct has only one physical unit, containing two reference values. Second, you can see the class declared, which contains two reference value members. When used, the two types will be stored in different memory locations (stack and heap).
Class ExamplesExample type declarations [C#]
struct ExampleStruct
{
public int[] _value1;
public int[] _value2;
public ExampleStruct(int[] value1, int[] value2)
{
this._value1 = value1;
this._value2 = value2;
}
}
class ExampleClass
{
public int[] _value1;
public int[] _value2;
public ExampleClass(int[] value1, int[] value2)
{
this._value1 = value1;
this._value2 = value2;
}
}
Here we look at how you can use the struct as a parameter to a method, and also how you can use the equivalent class. The Main entry point below creates an array that is stored as a field in both the struct and class instances. The MethodStruct function receives a struct parameter; the MethodClass function receives a class parameter.
Program that uses struct and class parameters [C#]
using System;
class Program
{
static int MethodStruct(ExampleStruct example)
{
return example._value1[0];
}
static int MethodClass(ExampleClass example)
{
return example._value1[0];
}
static void Main()
{
//
// Create a new array with value 5.
//
int[] array1 = new int[1];
array1[0] = 5;
Console.WriteLine("--- Array element assigned ---");
//
// Create new struct and class.
//
ExampleStruct example1 = new ExampleStruct(array1, array1);
ExampleClass example2 = new ExampleClass(array1, array1);
//
// Use struct and then class in method as parameters.
//
int value1 = MethodStruct(example1);
Console.WriteLine(value1);
int value2 = MethodClass(example2);
Console.WriteLine(value2);
//
// Change the value of the array element.
//
array1[0] = 10;
Console.WriteLine("--- Array element changed ---");
int value3 = MethodStruct(example1);
Console.WriteLine(value3);
int value4 = MethodClass(example2);
Console.WriteLine(value4);
}
}
Output
--- Array element assigned ---
5
5
--- Array element changed ---
10
10MethodStruct: This method receives a strongly-typed value of ExampleStruct type. When you call this method, the struct and all its fields will be physically copied onto the function stack. It can take significant time to copy structs when used as method parameters or even locals.
MethodClass: This method receives a strongly-typed value containing a reference to an ExampleClass object. In the C# language, an object is the actual data, while a reference is the variable that points to that data. The parameter here is a reference. Reference values are basically pointers and are very lightweight and efficient. Instantiating objects is more expensive.

Here we look at how using structs as parameters compares to using classes as parameters. For the benchmark, we test the Dictionary class's TryGetValue method. When you call methods on a collection like Dictionary, at least one set of parameters will be copied. The benchmark shows that large value types such as structs can slow down method calls when used as parameters.
Dictionary ExamplesData types tested [C#]
struct A
{
public int[] a;
public int[] b;
}
class B
{
public int[] a;
public int[] b;
}
Dictionary used to store objects [C#]
var d1 = new Dictionary<string, A>();
var d2 = new Dictionary<string, B>();
d1.Add("a", new A());
d2.Add("a", new B());
Code tested in loop [C#]
A a1;
if (d1.TryGetValue("a", out a1))
{
var x = a1.a;
}
B b1;
if (d2.TryGetValue("a", out b1))
{
var x = b1.a;
}
Benchmark results
100000000 iterations tested.
Also tested in reverse order (class then struct).
A) Struct used: 3721 ms
B) Class used: 3595 ms [faster]Testing with three and four fields. The performance of using structs as parameters continues to degrade with three and four fields. The class parameter, because it does not become larger, does not degrade as much. This means that when the struct increases the number of fields, each method call such as TryGetValue becomes more expensive.
3 fields Struct: 3907 ms Class: 3733 ms 4 fields Struct: 4803 ms Class: 3634 ms

Probably the most common optimization you can do with structs in your programs written in the C# language is to remove them and turn them into classes. When developing complex programs, you will usually extract methods. When you extract methods and call them with struct parameters, performance will degrade.
Note: I recommend only using structs when the design of your application is complete and you have performed benchmarking that proves structs are beneficial.

Structs and classes can be used as parameters in programs written in the C# language. We noted how structs are implemented when you use them as parameters, reviewing value types. Additionally, we saw a benchmark of how structs performance in methods, showing that structs will be slower than classes when the types have two or more fields.
Struct Examples