C# — Reference
Source: https://learn.microsoft.com/en-us/dotnet/csharp/
C
- Created: 2000 by Anders Hejlsberg at Microsoft; standardized as ECMA-334 / ISO/IEC 23270
- Latest stable: C# 14 with .NET 10 (LTS, Nov 2025); C# 15 in preview with .NET 11 (as of 2026-05)
- Paradigms: multi-paradigm — object-oriented, component, functional, declarative (LINQ), generic, async, pattern-oriented
- Typing: static, strong, nominal, with local type inference (
var); nullable reference types - Memory: GC (generational tracing);
Span<T>/ref structfor stack allocation;unsafe/fixedfor raw pointers - Compilation: compiled to CIL/MSIL, then JIT (RyuJIT) at runtime; NativeAOT for AOT to native binary; tiered compilation + on-stack-replacement
- Primary domains: enterprise/business apps, web (ASP.NET Core), cloud services, games (Unity), desktop (WPF/WinForms/MAUI), Azure functions, IoT
- Official docs: https://learn.microsoft.com/en-us/dotnet/csharp/
1. At a glance
- Owned by .NET Foundation with development led by Microsoft. Roslyn is the open-source compiler.
- Single cross-platform runtime: .NET (formerly .NET Core; unified since .NET 5). LTS releases on even-numbered .NET versions (.NET 6, 8, 10), STS on odd.
- C# 15 ships with .NET 11 (preview as of 2026-05); adds collection-expression arguments and union types.
- C# 14 / .NET 10 is current LTS.
- Cross-platform: Windows, Linux, macOS, iOS, Android, WebAssembly (Blazor), and embedded (NativeAOT).
2. Getting started
-
Install: Download .NET SDK from https://dotnet.microsoft.com/download (includes runtime + compiler + CLI). Linux:
apt install dotnet-sdk-10.0. macOS:brew install --cask dotnet-sdk. Windows:winget install Microsoft.DotNet.SDK.10. -
Version manager: dotnet SDK supports global.json to pin SDK per repo. Multiple SDKs co-install; CLI selects per
global.json. -
Hello, world (top-level statements, C# 9+):
Console.WriteLine("Hello, world!");Run:
dotnet new console -n hello && cd hello && dotnet run. -
Project layout:
MyApp.csproj+Program.cs; SDK-style projects (<Project Sdk="Microsoft.NET.Sdk">). Solutions (.sln) group projects. -
Build / package:
dotnetCLI (build,run,test,publish,pack); MSBuild under the hood. Packages from NuGet (https://nuget.org). -
REPL:
dotnet-script, C# Interactive (in Visual Studio), Polyglot Notebooks (Jupyter via .NET Interactive). SharpLab (https://sharplab.io) for compiler IL/asm exploration.
3. Basics
- Primitives:
bool,byte/sbyte,short/ushort,int/uint,long/ulong,nint/nuint,float,double,decimal,char,string. Literals:0x,0b,_digit separators (1_000_000), suffixesL,U,M(decimal),f/d. - Variables:
var x = 1;(inferred),const,readonly,static. Nullable annotations:string?vsstring. Block scope, no shadowing within scope. - Control flow:
if/else,switchstatement,switchexpression with patterns (x switch { > 0 => "+", _ => "0/-" }),for,foreach,while,do-while,goto. Pattern matching: type, property, list, relational, logical patterns. - Functions: static methods, instance methods, local functions, lambdas
(x, y) => x + y, expression-bodied membersint Square(int x) => x * x;. Optional/named args,params,ref/out/in, ref returns. Delegates (Func<>/Action<>) are first-class. - Strings: immutable
string. Interpolation:$"Hello {name}". Verbatim:@"C:\path". Raw string literals (C# 11):"""..."""with optional interpolation$$"""...""". UTF-8 string literals:"abc"u8. - Collections:
T[],List<T>,Dictionary<K,V>,HashSet<T>,Queue<T>,Stack<T>,LinkedList<T>, immutable variants (ImmutableArray<T>etc.),Span<T>/ReadOnlySpan<T>,Memory<T>. Collection expressions (C# 12):int[] x = [1, 2, 3];.
4. Intermediate
- Generics: type parameters on classes/methods/interfaces, constraints (
where T : class, IComparable<T>, new()), variance (in/out), default literaldefault(T), static abstract members in interfaces (C# 11) which enables generic math. - Modules/packages: assemblies (
.dll); namespaces (namespace Foo.Bar;file-scoped C# 10); NuGet packages distribute compiled assemblies.global usingdirectives. - Error handling: exceptions (
try/catch/finally/when), no checked exceptions.IExceptionHandlerin ASP.NET Core. Pattern: throw on exceptional, returnResult/Optiontypes via libraries (LanguageExt, OneOf) orbool TryX(out T)for hot paths. - Concurrency: Tasks (
Task/Task<T>) withasync/await.ValueTask<T>for hot paths. TPL Dataflow, Channels (System.Threading.Channels),IAsyncEnumerable<T>+await foreach. Threads (Thread),ThreadPool,SemaphoreSlim,Interlocked,lock(Monitor). PLINQ,Parallel.ForEach/Parallel.ForEachAsync. - I/O & networking:
System.IO(File,Stream,FileStream),System.IO.Pipelines(high-perf),HttpClient(andIHttpClientFactory),System.Net.Sockets,System.Net.WebSockets,gRPC.Net. - Stdlib highlights: LINQ (
System.Linq),System.Text.Json(default serializer; source-generated since .NET 7),Regex(with source generation),DateTime/DateTimeOffset/DateOnly/TimeOnly,TimeProvider(DI-friendly time),Random.Shared.
5. Advanced
- Memory & GC: generational (gen 0/1/2 + LOH + POH), workstation vs server GC (
<ServerGarbageCollection>), background GC, regions (.NET 7+) replace segments. Tuning viaDOTNET_GCHeapCount,DOTNET_gcServer,DOTNET_GCConserveMemory.Span<T>/ref structstack-only types avoid allocations.ArrayPool<T>.Sharedfor buffer reuse.IDisposable+usingfor unmanaged resources. - Concurrency deep dive: sync context vs
ConfigureAwait(false), async state machine (compiler rewrites methods intoIAsyncStateMachine),Taskcontinuations,ValueTaskreuse viaIValueTaskSource, lock-free withInterlocked/Volatile,MemoryBarrier. - FFI/interop: P/Invoke (
[DllImport]and source-generated[LibraryImport]since .NET 7), COM interop, C++/CLI bridge, DllImportResolver, fixed-size buffers inunsafestructs,Marshalclass. C++ via WinRT/CsWinRT. - Reflection:
System.Reflection,Type.GetType(),Activator.CreateInstance, attributes; DynamicMethod, Reflection.Emit, System.Linq.Expressions (compiled lambdas). Heavy reflection is incompatible with NativeAOT; use source generators instead. - Performance tooling: dotnet-trace, dotnet-counters, dotnet-dump, PerfView (Windows), BenchmarkDotNet (the standard for microbenchmarks), dotMemory/dotTrace (JetBrains), Visual Studio Profiler,
EventPipe+ OpenTelemetry. CrossGen2 AOT pre-JIT, R2R (ReadyToRun), ILVerify.
6. God mode
- Source generators (Roslyn): compile-time codegen via
IIncrementalGenerator. Used bySystem.Text.Json,LoggerMessage,Regex,LibraryImport, AOT serialization. Replaces runtime reflection in hot paths. - Roslyn analyzers + code fixes: ship custom diagnostics + auto-fixes as NuGet packages.
- Expression trees:
Expression<Func<T, bool>>is data, not code; LINQ providers (EF Core, IQueryable) parse and translate. Compile to delegates with.Compile()or interpret manually. Span<T>/ref struct/ref fields/ scoped refs: stack-only types,refreturns,ref readonly,scopedkeyword (C# 11) for lifetime control. Critical to high-perf APIs (Utf8JsonReader,SpanReader).unsafe+fixed+ pointers +stackalloc: raw memory, function pointers (delegate*<int, int>), pinning managed memory.- NativeAOT:
<PublishAot>true</PublishAot>produces a single native binary, no runtime JIT, no MSIL — but trims reflection/dynamic codegen. Requires source generators + trimming-friendly code. - Channels +
IAsyncEnumerable<T>: unbounded/bounded with backpressure, single/multi consumer; under the hood uses linked lists andIValueTaskSourceto recycle awaiter state. - IL inspection: ildasm, ILSpy, dnSpy, dotPeek. SharpLab shows IL + JIT asm in browser.
- Roslyn scripting (
Microsoft.CodeAnalysis.CSharp.Scripting): evaluate C# strings; powers REPLs and embeddable script engines. - Dynamic via DLR:
dynamickeyword +System.Linq.Expressions+DynamicObject/ExpandoObject— interop with Python/Ruby/JS-style late binding. UnsafeAccessor(.NET 8+): zero-overhead access to private members without reflection.- Custom interceptors (preview): a source generator can replace specific call sites at compile time.
7. Idioms & style
- Naming:
PascalCasefor types, methods, properties, events, namespaces, constants;camelCasefor parameters and local variables;_camelCasefor private fields;IPascalCasefor interfaces;TPascalCasefor type parameters. - Formatter:
dotnet format(built into SDK); EditorConfig (.editorconfig) is canonical for style + analyzer rules. Roslyn analyzers ship with the SDK. - Idiomatic patterns: prefer
varwhen the type is obvious; useusingforIDisposable; expression-bodied members for one-liners; records for value-equality types;initsetters; positional records for DTOs; pattern matching over downcasts;nameof()everywhere;requiredproperties (C# 11); primary constructors (C# 12);IReadOnlyList<T>in public APIs; nullable reference types enabled (<Nullable>enable</Nullable>). - Reviewers look for: missing
ConfigureAwait(false)in libraries, sync-over-async (.Result/.Wait()), boxing in hot paths, IEnumerable enumerated multiple times, missingIDisposable.Disposepaths, suppression of nullable warnings without justification, exception swallowing, blocking on UI thread.
8. Ecosystem
- Web: ASP.NET Core (MVC, Razor Pages, Minimal APIs, Blazor Server / Blazor WebAssembly), SignalR (real-time), YARP (reverse proxy).
- Cloud: .NET Aspire (orchestration), Azure SDK for .NET, Dapr.
- Data: Entity Framework Core, Dapper, Npgsql, MongoDB.Driver.
- Mobile/Desktop: .NET MAUI, Avalonia, Uno Platform, WPF, WinForms, WinUI 3.
- Games: Unity (C# scripting), Stride, Godot Mono, MonoGame.
- ML: ML.NET, TorchSharp, ONNX Runtime, Microsoft.SemanticKernel.
- Testing: xUnit (most common), NUnit, MSTest; Moq/NSubstitute/FakeItEasy; FluentAssertions; Bogus (test data); Verify (snapshot); Testcontainers.
- Doc tools: DocFX, XML doc comments (
///), Sandcastle. - Notable users: Microsoft (Bing, Office, Azure), Stack Overflow, Unity (engine + games), GitHub (parts), JetBrains (Rider/ReSharper internals), Bloomberg.
9. Gotchas
async voidswallows exceptions and breaks composition — only legal for event handlers.- Sync-over-async deadlocks in legacy SyncContext (ASP.NET Framework, WPF).
.Result/.Wait()is forbidden. IDisposablenot inusingequals leak. Resharper/analyzer catches it.- LINQ deferred execution:
var q = list.Where(...)doesn’t run until enumerated; multiple enumerations re-execute the query (and re-hit the database). - Captured loop variable (pre-C# 5 in
for, still pre-C# 9 in someforeachscenarios) — modern C# captures per-iteration. structmutation through interface = silent boxing.- Default value of reference types is
null; nullable reference types help but only as warnings. ==onstringis value equality; onobjectit’s reference. On records: value-based.DateTime.UtcNowvsDateTime.NowvsTimeProvider; preferDateTimeOffsetandTimeProvider.ConfigureAwait(false)discipline: mandatory in libraries, optional in app code with no SyncContext (ASP.NET Core has none).- NativeAOT incompatibilities: dynamic codegen,
Assembly.LoadFrom, untyped reflection over generics — all break trimming. Span<T>cannot be field of class, cannot escapeasync/iterators, cannot be in arrays.Equals/GetHashCodesymmetry: must override both; mutating a key in aDictionary<K,V>corrupts it.
10. Citations
- C# language documentation hub: https://learn.microsoft.com/en-us/dotnet/csharp/
- What’s new in C# 15 (collection expression args, union types; ships with .NET 11): https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-15
- C# language reference: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/
- C# language specification (draft): https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/readme
- .NET runtime configuration / GC tuning: https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector
- Roslyn (compiler) repo + feature status: https://github.com/dotnet/roslyn ; https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md
- NativeAOT: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/
- EditorConfig + dotnet format: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options
- NuGet: https://learn.microsoft.com/en-us/nuget/