1+ // Licensed to the .NET Foundation under one or more agreements.
2+ // The .NET Foundation licenses this file to you under the MIT license.
3+ // See the LICENSE file in the project root for more information.
4+
5+ // This extension is restricted to the .NET 5 because it shares the same BCL
6+ // across all targets, ensuring that the layout of our Nullable<T> mapping type
7+ // will be correct. Exposing this API on older targets (especially .NET Standard)
8+ // is not guaranteed to be correct and could result in invalid memory accesses.
9+ #if NET5_0
10+
11+ using System ;
12+ using System . Runtime . CompilerServices ;
13+
14+ namespace Microsoft . Toolkit . HighPerformance . Extensions
15+ {
16+ /// <summary>
17+ /// Helpers for working with the <see cref="Nullable{T}"/> type.
18+ /// </summary>
19+ public static class NullableExtensions
20+ {
21+ /// <summary>
22+ /// Returns a reference to the value of the input <see cref="Nullable{T}"/> instance, regardless of whether
23+ /// the <see cref="Nullable{T}.HasValue"/> property is returning <see langword="true"/> or not. If that is not
24+ /// the case, this method will still return a reference to the underlying <see langword="default"/> value.
25+ /// </summary>
26+ /// <typeparam name="T">The type of the underlying value</typeparam>
27+ /// <param name="value">The <see cref="Nullable{T}"/></param>
28+ /// <returns>A reference to the underlying value from the input <see cref="Nullable{T}"/> instance.</returns>
29+ /// <remarks>
30+ /// Note that attempting to mutate the returned reference will not change the value returned by <see cref="Nullable{T}.HasValue"/>.
31+ /// That means that reassigning the value of an empty instance will not make <see cref="Nullable{T}.HasValue"/> return <see langword="true"/>.
32+ /// </remarks>
33+ public static ref T DangerousGetValueOrDefaultReference < T > ( this ref T ? value )
34+ where T : struct
35+ {
36+ return ref Unsafe . As < T ? , RawNullableData < T > > ( ref value ) . Value ;
37+ }
38+
39+ /// <summary>
40+ /// Mapping type that reflects the internal layout of the <see cref="Nullable{T}"/> type.
41+ /// See https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/Nullable.cs.
42+ /// </summary>
43+ /// <typeparam name="T">The value type wrapped by the current instance.</typeparam>
44+ private struct RawNullableData < T >
45+ where T : struct
46+ {
47+ #pragma warning disable CS0649 // Unassigned fields
48+ public bool HasValue ;
49+ public T Value ;
50+ #pragma warning restore CS0649
51+ }
52+ }
53+ }
54+
55+ #endif
0 commit comments