Object Lifecycle Internals
Construction, virtual destruction, native ownership and compatibility-shaped disposal.
Native object model
System::Object is an abstract base for participating Sharp Runtime class hierarchies, not a hidden header attached to every C++ value. Construction, destruction, copying and moving remain ordinary C++. Its virtual destructor makes deletion through an Object base safe; it does not imply garbage collection.
System::GC is a compatibility no-op. It cannot find unreachable objects, break reference cycles, move allocations or extend a borrowed lifetime.
Ownership vocabulary
| Form | Use | Porting consequence |
|---|---|---|
| Stack/value member | Small values with clear containing lifetime | Copy/move follows the value type |
std::unique_ptr<T> | One transferable owner | Closest expression of exclusive ownership |
std::shared_ptr<T> | Genuinely shared lifetime | Cycles still leak unless a back edge is weak |
std::weak_ptr<T> | Observation without keeping the target alive | Lock and handle expiry at every use |
| Reference/raw pointer | Short, documented borrow or interop boundary | Owner must outlive every access |
| Span/Memory/ArraySegment | Borrowed view into existing storage | Reallocation or owner destruction invalidates the view |
Dispose-shaped APIs
Where present, Dispose aids source compatibility and deterministic release. The C++ destructor must still leave the type safe under scope exit and exception unwinding. A port should make repeated disposal and post-disposal behavior explicit rather than assuming the CLR contract.
Surfaces that need extra care
- Some collection enumerator and Keys/Values APIs return owning raw heap pointers; the caller must delete them.
MemoryHandlehas an explicit Dispose contract.- Reference-taking BlockingCollection constructors keep a no-delete shared wrapper; the referenced collection must outlive the wrapper.
- Several asynchronous socket, HTTP and WebSocket operations capture a raw owner or caller buffer; both must survive task completion.
- Delegates and event subscriptions keep the ownership expressed by their C++ captures—not a managed target root.
Copy, move and shutdown
For each resource-owning type, decide whether copying duplicates a value, shares a handle, or must be disabled. Moving must leave a destructible source. For asynchronous owners, shutdown normally means: prevent new work, request cancellation, wait or join, detach subscriptions, then release state.
The most dangerous compatibility bugs live where an API looks managed but stores a native borrow. Record the owner, invalidation events, and thread that may perform the last access.