C# Story

Chapter #3 – Data

types, values, initialization, nullable types, collections

3.0 Prologue

This chapter focuses on how C# represents and initializes data. The value-vs-reference distinction introduced in Chapter 1 becomes concrete here, along with the type system, nullable annotations, and the fundamental collection types.

3.1 Built-In Types

The table below lists the most commonly used built-in types. Each has a corresponding .NET struct type (e.g., intSystem.Int32).
Keyword .NET type Size Range / Notes
boolBoolean1 bytetrue / false
byteByte1 byte0..255
shortInt162 bytes−32 768..32 767
intInt324 bytes−2¹³ ..2¹³−1
longInt648 bytes−2&sup6;³..2&sup6;³−1
floatSingle4 bytes~7 decimal digits
doubleDouble8 bytes~15 decimal digits
decimalDecimal16 bytes28–29 digits; no rounding error
charChar2 bytesUTF-16 code unit
stringStringvariableimmutable UTF-16 sequence; reference type
objectObjectvariableroot of all types; reference type

3.2 Initialization

C# requires variables to be definitely assigned before use. Local variables have no implicit default; fields and array elements are zero-initialized. int a = 10; // explicit initialization var b = 3.14; // type inferred as double int[] arr = { 1, 2, 3 }; // array initializer var pt = new Point { X = 1, Y = 2 }; // object initializer var list = new List<int> { 1, 2, 3 }; // collection initializer (int x, string s) = (42, "hello"); // tuple deconstruction (C# 7+) Target-typed new (C# 9+) lets you omit the type on the right-hand side when it is already known from context: List<Point> pts = new();

3.3 Nullable Types

Nullable value types wrap a value type so it can also hold null: int? n = null;. The underlying type is Nullable<int>, which exposes .HasValue and .Value properties. Nullable reference types (C# 8+, enabled by <Nullable>enable</Nullable> in the project file) add compile-time warnings when a non-nullable reference may be null. Annotate nullable references with ?: string? name = null; Null-safe operators:
  • x?.Member — null-conditional; evaluates to null if x is null
  • x ?? y — null-coalescing; returns y when x is null
  • x ??= y — assigns y to x only if x is null

3.4 Enums and Structs

Enums define a named set of integer constants: enum Direction { North, South, East, West } Direction d = Direction.North; Structs are value types suited for small data containers. They are copied on assignment and should ideally be immutable: readonly struct Point { public double X { get; init; } public double Y { get; init; } public double Length => Math.Sqrt(X*X + Y*Y); }

3.5 Strings

Strings are immutable reference types. String literals support escape sequences ("\n", "\t"), verbatim strings (@"C:\Users"), and interpolated strings ($"Hello, {name}!"). Because strings are immutable, heavy concatenation should use StringBuilder to avoid creating many intermediate string objects. Equality comparison with == compares content (not reference) for strings, unlike other reference types.

3.6 Arrays and Spans

Arrays are fixed-size, zero-indexed, reference-type collections: int[] arr = new int[5]; Multi-dimensional arrays: int[,] matrix = new int[3, 4]; Jagged arrays: int[][] rows = new int[3][]; Span<T> and ReadOnlySpan<T> (C# 7.2+) provide stack-allocated slices over arrays, strings, or managed memory without copying, enabling high-performance data processing.

3.7 Tuples and Records

Value tuples bundle heterogeneous values without defining a class: (int id, string name) person = (1, "Alice"); Records (C# 9+) generate a class (or struct) with immutable properties, structural equality, and a with expression for non-destructive mutation: record Person(string Name, int Age); var alice = new Person("Alice", 30); var older = alice with { Age = 31 }; // creates a new record

3.8 Epilogue

This chapter covered the core data constructs of C#. The next chapter focuses on operations — how data is transformed through methods, delegates, and LINQ.

3.9 References

C# types — Microsoft docs
Nullable value types
Records — Microsoft docs
Span<T> / Memory<T> — Microsoft docs