mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2024-11-24 07:42:45 +01:00
75 lines
3.4 KiB
C#
75 lines
3.4 KiB
C#
// Licensed to the .NET Foundation under one or more agreements.
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
// This extension is restricted to the .NET 6 because it shares the same BCL
|
|
// across all targets, ensuring that the layout of our Nullable<T> mapping type
|
|
// will be correct. Exposing this API on older targets (especially .NET Standard)
|
|
// is not guaranteed to be correct and could result in invalid memory accesses.
|
|
|
|
#if NET6_0_OR_GREATER
|
|
|
|
using System;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace CommunityToolkit.HighPerformance;
|
|
|
|
/// <summary>
|
|
/// Helpers for working with the <see cref="Nullable{T}"/> type.
|
|
/// </summary>
|
|
public static class NullableExtensions
|
|
{
|
|
/// <summary>
|
|
/// Returns a reference to the value of the input <see cref="Nullable{T}"/> instance, regardless of whether
|
|
/// the <see cref="Nullable{T}.HasValue"/> property is returning <see langword="true"/> or not. If that is not
|
|
/// the case, this method will still return a reference to the underlying <see langword="default"/> value.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the underlying value.</typeparam>
|
|
/// <param name="value">The <see cref="Nullable{T}"/>.</param>
|
|
/// <returns>A reference to the underlying value from the input <see cref="Nullable{T}"/> instance.</returns>
|
|
/// <remarks>
|
|
/// Note that attempting to mutate the returned reference will not change the value returned by <see cref="Nullable{T}.HasValue"/>.
|
|
/// That means that reassigning the value of an empty instance will not make <see cref="Nullable{T}.HasValue"/> return <see langword="true"/>.
|
|
/// </remarks>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static ref T DangerousGetValueOrDefaultReference<T>(this ref T? value)
|
|
where T : struct
|
|
{
|
|
return ref Unsafe.As<T?, RawNullableData<T>>(ref value).Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a reference to the value of the input <see cref="Nullable{T}"/> instance, or a <see langword="null"/> <typeparamref name="T"/> reference.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the underlying value.</typeparam>
|
|
/// <param name="value">The <see cref="Nullable{T}"/>.</param>
|
|
/// <returns>A reference to the value of the input <see cref="Nullable{T}"/> instance, or a <see langword="null"/> <typeparamref name="T"/> reference.</returns>
|
|
/// <remarks>The returned reference can be tested for <see langword="null"/> using <see cref="Unsafe.IsNullRef{T}(ref T)"/>.</remarks>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static unsafe ref T DangerousGetValueOrNullReference<T>(ref this T? value)
|
|
where T : struct
|
|
{
|
|
if (value.HasValue)
|
|
{
|
|
return ref Unsafe.As<T?, RawNullableData<T>>(ref value).Value;
|
|
}
|
|
|
|
return ref Unsafe.NullRef<T>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mapping type that reflects the internal layout of the <see cref="Nullable{T}"/> type.
|
|
/// See https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/Nullable.cs.
|
|
/// </summary>
|
|
/// <typeparam name="T">The value type wrapped by the current instance.</typeparam>
|
|
private struct RawNullableData<T>
|
|
where T : struct
|
|
{
|
|
#pragma warning disable CS0649 // Unassigned fields
|
|
public bool HasValue;
|
|
public T Value;
|
|
#pragma warning restore CS0649
|
|
}
|
|
}
|
|
|
|
#endif |