Как указано pinkfloydx33 в комментариях к этим вопросам, в пакете System.Runtime.CompilerServices.Unsafe NuGet есть класс Unsafe
.С его помощью вы можете бросить на ulong небезопасным способом, который не выделяет.Если мы изменим эталонный класс из моего вопроса следующим образом:
public class ToUInt64Benchmark
{
public BindingFlags FlagsValue = BindingFlags.Public | BindingFlags.Instance;
public IConvertible FlagsValueAsConvertible;
public ToUInt64Benchmark() => FlagsValueAsConvertible = FlagsValue;
[Benchmark(Baseline = true)]
public ulong EnumToUInt64() => FlagsValueAsConvertible.ToUInt64(null);
[Benchmark]
public ulong UnsafeEnumToUInt64() => ConvertUnsafe(FlagsValue);
private static unsafe ulong ConvertUnsafe<T>(T enumValue) where T : struct, Enum
{
var pointer = (ulong*)Unsafe.AsPointer(ref enumValue);
return *pointer;
}
}
... это приведет к следующим результатам:
Это намного быстрее (только 10% времени выполнения ToUInt64
в .NET Core 2.2 на моем Surface Pro 4) и, самое главное, он не выделяется.
Пожалуйста, обязательнодобавьте тег AllowUnsafeBlocks
в файл csproj, чтобы разрешить компиляцию небезопасного кода.Вы не можете запустить этот код на частично доверенных платформах (например, Silverlight).Вот структура моего файла csproj.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.2;net472</TargetFrameworks>
<DebugType>portable</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.11.3" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
</ItemGroup>
</Project>
Обновление 2018-12-26 17:00 UTC
Как pinkfloydx33 правильно указано в комментариях (один разснова), код можно упростить с помощью Unsafe.As
:
public class ToUInt64Benchmark
{
// Other members omitted for brevity's sake
[Benchmark]
public ulong UnsafeEnumToUInt64() => ConvertUnsafe(FlagsValue);
private static ulong ConvertUnsafe<T>(T enumValue) where T : struct, Enum =>
Unsafe.As<T, ulong>(ref enumValue);
}
Это не влияет на производительность, но для него не требуется тег AllowUnsafeBlocks
в файле csproj.