Defensive Copying in C# Example
Defensive copying is a technique used to prevent external code from modifying an object's state. This is achieved by creating a new instance of the object, copying the original object's properties to the new instance.
In C#, this can be implemented using a Lazy<T> object, which provides support for lazy initialization. This means the object is not created until it is accessed for the first time, improving performance by avoiding unnecessary computation.
Here's an example from a ProblemDetailsResult<T> class:
In this ProblemDetailsResult<T> example:
The
initaccessor forProblemDetailsstores the originally providedProblemDetailsobject in the private field_initialProblemDetails.The
getaccessor returns_problemDetailsLazy.Value.The
Lazy<T>object (_problemDetailsLazy) is initialized with theCreateExtendedProblemDetailsfactory method.When
ProblemDetailsis accessed for the first time,CreateExtendedProblemDetailsis executed.Inside
CreateExtendedProblemDetails, a newProblemDetailsobject (detailsCopy) is created. Its properties are populated from_initialProblemDetails. Crucially, theExtensionsdictionary, which is mutable, is also copied into a newDictionaryinstance. This prevents changes to the copied extensions from affecting the original object's extensions dictionary.Additional context-specific information (
SourceId,CallerMemberName) is added to the copy'sExtensions.This newly created and modified
detailsCopyis returned and cached by theLazy<T>. Subsequent accesses toProblemDetailsreturn this cached copy.
This ensures that the ProblemDetails object exposed by the ProblemDetailsResult<T> is a distinct instance from the one initially provided, protecting the internal state and adding context without modifying the original object.
See Also:
Functional in the Small and Object-Oriented in the Large (discusses immutability techniques)
Transitioning from Classes to Records and Adopting Immutable Collections in C#