diff --git a/DeeDee/Builders/Models/FrugalDictionaryBuilder.cs b/DeeDee/Builders/Models/FrugalDictionaryBuilder.cs index 9a64903..c490dc1 100644 --- a/DeeDee/Builders/Models/FrugalDictionaryBuilder.cs +++ b/DeeDee/Builders/Models/FrugalDictionaryBuilder.cs @@ -43,161 +43,165 @@ private static bool TryCheck(ref KeyValuePair kvp, object key, public bool TryGetValue(object key, out object? value) { - value = FindEntry(key); - return value != null; + var (found, val) = FindEntry(key); + value = val; + return found; } - private object? FindEntry(object key) + private static (bool Found, object? Value) Found(object? value) => (true, value); + private static (bool Found, object? Value) NotFound() => (false, null); + + private (bool Found, object? Value) FindEntry(object key) { switch (_allocated) { - case 0: return null; + case 0: return NotFound(); case 1: { - return TryCheck(ref _one, key, out var val) ? val : null; + return TryCheck(ref _one, key, out var val) ? Found(val) : NotFound(); } case 2: { if (TryCheck(ref _one, key, out var val)) - return val; - return TryCheck(ref _two, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _two, key, out val) ? Found(val) : NotFound(); } case 3: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; - return TryCheck(ref _three, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _three, key, out val) ? Found(val) : NotFound(); } case 4: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; - return TryCheck(ref _four, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _four, key, out val) ? Found(val) : NotFound(); } case 5: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; - return TryCheck(ref _five, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _five, key, out val) ? Found(val) : NotFound(); } case 6: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; + return Found(val); if (TryCheck(ref _five, key, out val)) - return val; - return TryCheck(ref _six, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _six, key, out val) ? Found(val) : NotFound(); } case 7: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; + return Found(val); if (TryCheck(ref _five, key, out val)) - return val; + return Found(val); if (TryCheck(ref _six, key, out val)) - return val; - return TryCheck(ref _seven, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _seven, key, out val) ? Found(val) : NotFound(); } case 8: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; + return Found(val); if (TryCheck(ref _five, key, out val)) - return val; + return Found(val); if (TryCheck(ref _six, key, out val)) - return val; + return Found(val); if (TryCheck(ref _seven, key, out val)) - return val; - return TryCheck(ref _eight, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _eight, key, out val) ? Found(val) : NotFound(); } case 9: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; + return Found(val); if (TryCheck(ref _five, key, out val)) - return val; + return Found(val); if (TryCheck(ref _six, key, out val)) - return val; + return Found(val); if (TryCheck(ref _seven, key, out val)) - return val; + return Found(val); if (TryCheck(ref _eight, key, out val)) - return val; - return TryCheck(ref _nine, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _nine, key, out val) ? Found(val) : NotFound(); } case 10: { if (TryCheck(ref _one, key, out var val)) - return val; + return Found(val); if (TryCheck(ref _two, key, out val)) - return val; + return Found(val); if (TryCheck(ref _three, key, out val)) - return val; + return Found(val); if (TryCheck(ref _four, key, out val)) - return val; + return Found(val); if (TryCheck(ref _five, key, out val)) - return val; + return Found(val); if (TryCheck(ref _six, key, out val)) - return val; + return Found(val); if (TryCheck(ref _seven, key, out val)) - return val; + return Found(val); if (TryCheck(ref _eight, key, out val)) - return val; + return Found(val); if (TryCheck(ref _nine, key, out val)) - return val; - return TryCheck(ref _ten, key, out val) ? val : null; + return Found(val); + return TryCheck(ref _ten, key, out val) ? Found(val) : NotFound(); } default: { - return _values!.TryGetValue(key, out var val) ? val : null; + return _values!.TryGetValue(key, out var val) ? Found(val) : NotFound(); } } } - public object this[object key] + public object? this[object key] { get { var entry = FindEntry(key); - if (entry == null) - throw new KeyNotFoundException(); - return entry; + if (!entry.Found) + ThrowHelper.ThrowKeyNotFound(); + return entry.Value; } } diff --git a/DeeDee/Builders/Models/ThrowHelperBuilder.cs b/DeeDee/Builders/Models/ThrowHelperBuilder.cs new file mode 100644 index 0000000..eeed337 --- /dev/null +++ b/DeeDee/Builders/Models/ThrowHelperBuilder.cs @@ -0,0 +1,25 @@ +namespace DeeDee.Builders.Models +{ + internal static class ThrowHelperBuilder + { + public static string Build() + { + return @" +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace DeeDee.Models +{ + internal static class ThrowHelper + { + [DoesNotReturn] + public static void ThrowKeyNotFound() + { + throw new KeyNotFoundException(); + } + } +} +"; + } + } +} diff --git a/DeeDee/DeeDee.csproj b/DeeDee/DeeDee.csproj index 8979823..d5a1c5c 100644 --- a/DeeDee/DeeDee.csproj +++ b/DeeDee/DeeDee.csproj @@ -13,7 +13,7 @@ https://github.com/joh-pot/DeeDee/wiki https://github.com/joh-pot/DeeDee CQRS, command, queries, request, response, source generation - 1.0.5 + 1.0.6 Apache-2.0 diff --git a/DeeDee/SourceGenerator.cs b/DeeDee/SourceGenerator.cs index 70a0b49..3f575da 100644 --- a/DeeDee/SourceGenerator.cs +++ b/DeeDee/SourceGenerator.cs @@ -26,6 +26,7 @@ public void Execute(GeneratorExecutionContext context) var pipelineContext = PipelineContextBuilder.Build(); var serviceProviderDelegate = ServiceProviderDelegateBuilder.Build(); var stepAttribute = StepAttributeBuilder.Build(); + var throwHelper = ThrowHelperBuilder.Build(); context.AddSource("FrugalDictionary.cs", frugalDictionary); context.AddSource("IPipelineAction.cs", ipipelineAction); @@ -34,6 +35,7 @@ public void Execute(GeneratorExecutionContext context) context.AddSource("PipelineContext.cs", pipelineContext); context.AddSource("ServiceProviderDelegate.cs", serviceProviderDelegate); context.AddSource("StepAttribute.cs", stepAttribute); + context.AddSource("ThrowHelper.cs", throwHelper); var options = (context.Compilation as CSharpCompilation)!.SyntaxTrees[0].Options as CSharpParseOptions;