using System.Linq.Expressions;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Emit;
public static class Programm
const int rounds = 100000;
public static void Main()
var boolPlain = new BoolPlain{ TypedValue = true };
BenchmarkTools.MeasurePerformance("Plain", () =>
for (var i = 0; i < rounds; i++)
boolPlain.As<int>(out _);
public class BoolPlain : ValuePlain<bool>
private static readonly IReadOnlyDictionary<Type, Delegate> k_Conversions = new Dictionary<Type, Delegate>
{ typeof(int), new Func<bool, int>(value => value ? 1 : 0) },
{ typeof(float), new Func<bool, float>(value => value ? 1.0f : 0.0f) },
{ typeof(double), new Func<bool, double>(value => value ? 1.0 : 0.0) }
protected override IReadOnlyDictionary<Type, Delegate> Conversions => k_Conversions;
public abstract class ValuePlain<T> : IValue
public T TypedValue { get => m_Value; set => m_Value = value; }
public bool As<TTarget>(out TTarget result)
if (m_Value is TTarget target)
if (Conversions.TryGetValue(typeof(TTarget), out var conversion) && conversion is Func<T, TTarget> converter)
result = converter(TypedValue);
if (k_DefaultConversions.TryGetValue(typeof(TTarget), out var defaultConversion))
result = (TTarget)defaultConversion(TypedValue);
private static readonly IReadOnlyDictionary<Type, Func<T, object>> k_DefaultConversions = new Dictionary<Type, Func<T, object>>
value => value.ToString()
protected abstract IReadOnlyDictionary<Type, Delegate> Conversions { get; }
public static class BenchmarkTools
public static void MeasurePerformance(string approach, Action action)
var stringBuilder = new StringBuilder($"Performance Measurement: {approach}\n ");
GC.WaitForPendingFinalizers();
var stopwatch = Stopwatch.StartNew();
stringBuilder.Append($" Execution Time: {stopwatch.ElapsedMilliseconds} ms\n");
var memoryBefore = GC.GetTotalMemory(true);
var memoryAfter = GC.GetTotalMemory(false);
stringBuilder.Append($" Allocations: {NicifyMemory(memoryAfter - memoryBefore)}\n");
Console.WriteLine(stringBuilder.ToString());
private static string NicifyMemory(long bytes)
< 1024 * 1024 => $"{bytes / 1024} KB",
_ => $"{bytes / (1024 * 1024)} MB"};
bool As<TTarget>(out TTarget result);