CSharpStory_Survey.html
copyright © James Fawcett
Revised: 04/26/2026
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