Runtime Overview

Understand the complete runtime from core native representations through collections, data, I/O, networking, concurrency, and platform services.

Subsystem mapNative C++23Source-backed

How to read the runtime

Sharp Runtime is easier to understand as a set of subsystem families than as a flat list of more than a thousand public headers. The lowest layer supplies native representations and contracts. Above it sit collections, text and data, I/O, networking, concurrency, and platform-facing utilities. Each family remains selectable through a physical CMake graph.

Representation map

C# / .NET conceptSharp Runtime / C++ representationImportant difference
stringSharpRuntime::String = std::string; System::String static helpersUTF-8 byte storage, mutable native value, no managed null or interning contract
T[]std::vector<T> plus System::Array algorithmsVector owns and can reallocate; no CLR array base or runtime covariance
Span<T>Pointer and signed element lengthNon-owning; source storage must outlive it
Memory<T>Borrowed vector plus offset and lengthDoes not retain a managed owner; Pin only exposes native storage
Nullable<T>Wrapper over std::optional<T>Contained C++ value’s copy, move, and destruction semantics remain visible
objectOpt-in System::Object hierarchy or an unrelated native valueNo universal root, boxing header, or GC identity
TypeWrapper around std::type_infoIdentity only; no member metadata or dependable CLR classification
Delegate/eventTyped C++ callables and handler collectionsCapture and subscription lifetime are native and explicit
TaskNative task/continuation objects and scheduler abstractionsNo C# language async/await state machine or CLR synchronization context guarantee

Foundation: Core.Base and narrow core components

Core.Base is the largest foundational owner. It supplies fixed-width aliases, Object, Type, numeric wrappers, exceptions, arrays and views, nullable values, delegates, environment/version helpers, and many other contracts used by higher layers. Console, Uri, and TimeZone are separate physical components so applications can avoid unrelated platform code; the compatibility target Core aggregates them for older consumers.

The core layer is intentionally heterogeneous. System::String and System::Array are static algorithm containers over standard native storage. Object is a polymorphic base only for participating hierarchies. Numeric wrappers and nullable values are ordinary value-like C++ types. This is more honest and useful than forcing every API into an artificial CLR-shaped object.

Collections and buffers

Buffers provides span-oriented and binary/text buffer contracts. The collection family is split into synchronous core collections, blocking producer/consumer support, async enumeration contracts, and object-model/observable collections. This split keeps threading and component-model dependencies out of applications that only need a list or dictionary.

Native ownership affects every collection choice. A List<Widget>-shaped container of values copies or moves widgets; a container of shared_ptr values shares identity; a container of raw pointers merely borrows. Mutation can invalidate iterators, enumerators, references, spans, and views. Concurrent containers coordinate their own structure, not the thread safety of stored objects.

Text, JSON, regular expressions, and XML

The Text component supplies builders, encodings, formatting, Base64, web encoders, and Unicode-shaped helpers around the project’s UTF-8 byte-string model. It does not turn std::string into a UTF-16 CLR string. Index units, case conversion, normalization, collation, and grapheme behavior therefore need explicit evaluation.

Text.Json wraps a vendored nlohmann JSON backend with familiar documents, nodes, readers, writers, serializers, options, and converters. It is broad enough for real native data work, but it is not reflection-driven serializer parity or a source generator. Text.RegularExpressions exposes a curated regex family over a native backend; .NET-only constructs and Unicode/culture behavior are not inferred from matching names.

Xml owns readers, writers, documents, schema, and XPath-shaped behavior over tinyxml2. Xml.Linq adds names, nodes, elements, attributes, documents, and LINQ-to-XML-shaped operations. Recent remediation corrected namespace lookup, lexical validation, embedded NUL handling, document-type parsing, and other strictness boundaries. XPath variables, custom functions, and a general extension context remain outside the supported subset.

I/O, compression, hashing, and storage

The IO component contains the abstract stream model, memory and file streams, binary and text readers/writers, file and directory helpers, metadata wrappers, random access, drives, unmanaged memory streams, and FileSystemWatcher. Capability properties and lifecycle must be consulted per stream; not every base operation is abstract or supported in the same way as .NET.

Compression and ZIP are separate owners. IO.Compression uses ZLIB privately; IO.Compression.Zip uses vendored miniz. IO.Hashing holds checksums and non-cryptographic hashes, which should never be presented as security primitives. Storage resolves application paths, while IO.IsolatedStorage builds store-relative operations and confinement checks over the filesystem. It is not an OS-enforced sandbox.

FileSystemWatcher is deliberately documented as Linux/inotify-only at this pin. The current remediation makes self-disable from a callback safe and contains handler failures, but recursive watching and live notify-filter remapping remain limited. See the dedicated watcher page rather than extrapolating from the class name.

Networking

The networking family separates base address/DNS types, sockets, HTTP messages and transport, headers, HTTP/JSON integration, MIME, network information, security-shaped contracts, and WebSockets. This keeps a consumer’s direct need visible even though CMake resolves the shared closure.

Windows and POSIX socket implementations exist; host DNS, interfaces, raw sockets, ICMP permissions, and IPv6 configuration remain environment inputs. HTTP is currently buffered plain HTTP/1.1 over TCP. WebSockets support ws://. Certificates, SslStream, HTTPS, and wss:// are not supplied merely because Net.Security contains familiar names.

Threading, tasks, channels, and timers

Threading supplies native threads, monitors, events, locks, cancellation, synchronization contexts, atomics, and thread-pool-shaped behavior. Threading.Tasks adds tasks, completion sources, continuations, schedulers, and aggregate coordination. Threading.Channels adds bounded and unbounded channel readers and writers. Timers dispatches delayed or periodic callbacks.

These facilities help preserve familiar control-flow shapes, but they cannot import C# language semantics into C++. Every asynchronous path needs an owner, cancellation strategy, exception-observation path, and shutdown protocol. Capturing a raw pointer does not retain it. A callback can race destruction or reconfiguration unless the concrete type documents serialization.

Numerics, globalization, diagnostics, runtime, and security

Numerics includes vectors, matrices, quaternion, BigInteger, Complex, Decimal, and wide numeric wrappers. Correctness remediation covers overflow, parsing, special floating-point values, rounding, and defined arithmetic, but compiler capability remains visible: native __int128 is required by some surfaces and constrains current MSVC coverage.

Globalization supplies cultures, calendars, regions, comparison options, and parsing/formatting data. It is not ICU or the full .NET data set. Diagnostics provides debug, trace, stopwatch, process, stack, and analysis-shaped APIs with platform-specific depth. Runtime holds compiler-services, interop, serialization markers, handles, and runtime helpers without implementing a CLR.

The security family offers principals, permissions, authentication-shaped contracts, hashes, HMAC, PBKDF2, cryptographic operations, and platform secure random. It does not amount to a complete encryption/certificate/TLS platform. Security promises are made per algorithm and transport, not per namespace.

Component graph and external attachment

At the pinned SHA the runtime has 41 physical components and 92 direct production edges. Header-only components can only have public dependencies; compiled components may hide implementation dependencies privately. Tests have their own edges and cannot expand the production surface. ZLIB, miniz, tinyxml2, nlohmann JSON, platform socket libraries, BCrypt, and Android SDL3 are attached by their owning component rather than globally.

Use the component catalogue to select a target, the API inventory to locate public entries, and the conceptual pages to understand semantics. Those layers are complementary: a generated header list alone cannot explain ownership or a Unicode reduction, while prose alone should not hand-maintain 1,036 public header names.

Verification snapshot

The selected source registers 37 physical component test executables and one integration executable. The complete measured gate at that same SHA discovered and ran 17,131 GoogleTest cases: 17,123 passed, two skipped, and six failed. Five failures expose a Ping/raw-ICMP fallback gap under the host’s ping-group policy; one depends on missing IPv6 host state. Component graph, selective consumer, negative boundary, catalogue, and documentation checks provide evidence that a large pass count cannot provide by itself.

Choose a path