C# Story

Chapter #2 – C# Survey

data, operations, classes, generics, libraries

2.0 Survey Prologue

This chapter provides a brief survey of the major C# language features. Each topic is discussed in much more detail in subsequent chapters. The goal here is to give you enough of a map that the later chapters feel like familiar territory.

2.1 Types

C# is a statically typed language. Every variable, parameter, and return value has a type known at compile time. Built-in value types: bool, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal, char. Built-in reference types: string, object, dynamic. User-defined value types: struct, enum, record struct. User-defined reference types: class, interface, delegate, record. Type inference: Use var to let the compiler infer the type from the initializer: var x = 42; Nullable types: Any type can be made nullable by appending ?: int? n = null; or string? s = null;

2.2 Control Flow

Standard statements: if / else, switch, for, foreach, while, do / while, break, continue, return, throw. C# switch supports pattern matching (C# 7+): string Describe(object o) => o switch { int n when n < 0 => "negative int", int => "non-negative int", string => "string", null => "null", _ => "something else" }; foreach works with any type that implements IEnumerable<T>, including arrays, lists, dictionaries, and custom collections.

2.3 Methods

Methods are defined inside types. Parameters are passed by value by default. ref passes by reference, out is a by-reference output parameter, and in is a read-only reference. Methods can be overloaded (same name, different parameter lists). C# supports optional parameters with defaults and named arguments. Expression-bodied members (C# 6+): int Square(int x) => x * x; Local functions (C# 7+): a method defined inside another method, invisible to the outer type.

2.4 Delegates, Events, and Lambdas

A delegate is a type-safe function pointer. The BCL provides Action<T> (returns void) and Func<T, TResult> (returns a value) so you rarely need to declare your own delegate types. Lambda expressions are anonymous methods written inline: Func<int,int> sq = x => x * x; Events are delegate fields exposed through the event keyword. Subscribers use += and -= to attach and detach handlers. LINQ (Language Integrated Query) uses delegates and extension methods to query any IEnumerable<T> with a SQL-like syntax: var evens = from n in numbers where n % 2 == 0 orderby n select n * n; // or equivalently with method syntax: var evens = numbers.Where(n => n % 2 == 0).OrderBy(n => n).Select(n => n * n);

2.5 Classes

A C# class bundles data (fields) and behavior (methods). Access is controlled with public, private, protected, internal, and protected internal modifiers. Properties expose data through get/set accessors and are preferred over public fields: public class Point { public double X { get; set; } public double Y { get; set; } public double Length => Math.Sqrt(X*X + Y*Y); } Constructors initialize instances. C# generates a default parameterless constructor only if no constructor is defined. Static members belong to the type, not to any instance. Static classes can contain only static members (useful for utility/extension method classes).

2.6 Inheritance and Interfaces

C# supports single implementation inheritance for classes and multiple interface implementation. Interfaces define contracts without implementation (though default interface methods were added in C# 8). Abstract classes provide partial implementation and cannot be instantiated directly. A class marked sealed cannot be derived from. Virtual methods use the virtual keyword in the base class; derived classes use override. New method hiding (not overriding) uses new.

2.7 Generics

Generics let you write type-safe code that works with many types without duplication: List<T>, Dictionary<TKey, TValue>, IEnumerable<T>. Generic constraints narrow acceptable type arguments: where T : class, where T : struct, where T : new(), where T : IComparable<T>.

2.8 Async / Await

C# has first-class support for asynchronous programming via async / await and the Task / Task<T> types: async Task<string> FetchAsync(string url) { using var http = new HttpClient(); return await http.GetStringAsync(url); } An async method runs synchronously until the first await of an incomplete task, then suspends without blocking the thread. The CLR schedules the continuation when the awaited work completes.

2.9 Epilogue

This survey covered the shape of the C# language. Subsequent chapters look at each area in detail with code examples and design guidance.

2.10 References

Tour of C# — Microsoft docs
C# Fundamentals — Microsoft docs
LINQ — Microsoft docs