56 lines
2.0 KiB
C#
56 lines
2.0 KiB
C#
namespace QWERTYkez.Mensura.Extensions;
|
||
|
||
public static partial class CastExtensions
|
||
{
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
internal static double ToDouble<T>(this T unit)
|
||
where T : struct, IMensuraUnit, IEquatable<T>
|
||
{
|
||
return Unsafe.As<T, double>(ref unit);
|
||
}
|
||
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
internal static T ToUnit<T>(this double val)
|
||
where T : struct, IMensuraUnit, IEquatable<T>
|
||
{
|
||
return Unsafe.As<double, T>(ref val);
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
internal static void SetCountUnsafe<T>(this List<T> list, int count)
|
||
{
|
||
// Берем адрес управляемого объекта List в памяти
|
||
// Объект передается по ref-ссылке, преобразуется в указатель
|
||
ref var mimic = ref Unsafe.As<List<T>, ListLayoutMimic<T>>(ref list);
|
||
|
||
// Меняем приватный размер напрямую в памяти объекта!
|
||
mimic.Size = count;
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
internal static List<T> WrapAsList<T>(this T[] array)
|
||
{
|
||
// Создаём пустой список с нулевой ёмкостью
|
||
var list = new List<T>(0);
|
||
|
||
// Получаем внутреннюю структуру списка
|
||
ref var mimic = ref Unsafe.As<List<T>, ListLayoutMimic<T>>(ref list);
|
||
|
||
// Подменяем массив и устанавливаем размер
|
||
mimic.Items = array;
|
||
mimic.Size = array.Length;
|
||
mimic.Version = 1; // любое ненулевое значение для консистенции
|
||
|
||
return list;
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
internal static List<R> WrapAsList<T, R>(this T[] array)
|
||
where T : struct, IMensuraUnit, IEquatable<T>
|
||
where R : struct, IMensuraUnit, IEquatable<R>
|
||
{
|
||
return Unsafe.As<T[], R[]>(ref array).WrapAsList();
|
||
}
|
||
} |