TheDeveloperBlog.com

Home | Contact Us

C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML

C# Struct Versus Class

This C# tutorial is about the memory usage of structs versus classes.

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.

Example. First, here are two type declarations. 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.

And: Second, you can see the class declared, which contains two reference value members.

Class

Tip: When used, the two types will be stored in different memory locations (stack and heap).

Example 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;
    }
}

Example 2. We can use the struct as a parameter. Here we create 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.

C# program that uses struct and class parameters

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
10

MethodStruct. 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.

And: The runtime can take significant time to copy structs when used as method parameters or even locals.

MethodClass receives a strongly-typed value containing a reference to an ExampleClass object. In the C# language, an object is the actual data. A reference is the variable that points to that data. The parameter here is a reference.

Tip: Reference values are basically pointers and are very lightweight and efficient. Instantiating objects is more expensive.

Benchmark. 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. Large value types such as structs can slow down method calls.

Dictionary

Data 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]

We find that 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.

And: 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

Discussion. A common optimization you can do with structs in your programs is to remove them and turn them into classes. When developing complex programs, you will usually extract methods. When you call methods with structs, performance degrades.

Tip: I recommend only using structs when the design of your application is complete.

And: Before adding custom structs, be sure to perform benchmarking that proves structs are beneficial.

Summary. Structs and classes can be used as parameters in C# programs. We noted how structs are implemented when you use them as parameters, reviewing value types. We also saw a benchmark of how structs perform in methods.


Related Links

Adjectives Ado Ai Android Angular Antonyms Apache Articles Asp Autocad Automata Aws Azure Basic Binary Bitcoin Blockchain C Cassandra Change Coa Computer Control Cpp Create Creating C-Sharp Cyber Daa Data Dbms Deletion Devops Difference Discrete Es6 Ethical Examples Features Firebase Flutter Fs Git Go Hbase History Hive Hiveql How Html Idioms Insertion Installing Ios Java Joomla Js Kafka Kali Laravel Logical Machine Matlab Matrix Mongodb Mysql One Opencv Oracle Ordering Os Pandas Php Pig Pl Postgresql Powershell Prepositions Program Python React Ruby Scala Selecting Selenium Sentence Seo Sharepoint Software Spellings Spotting Spring Sql Sqlite Sqoop Svn Swift Synonyms Talend Testng Types Uml Unity Vbnet Verbal Webdriver What Wpf