From 5343c2f87c38f8879b45134c76e98ad5b765d31a Mon Sep 17 00:00:00 2001 From: ancplua Date: Thu, 30 Apr 2026 22:59:22 +0200 Subject: [PATCH] refactor!: drop redundant/ambiguous dictionary extensions from TryExtensions Remove GetOrNull (redundant with BCL GetValueOrDefault), GetOrDefault (same), and all IDictionary/IList overloads that cause ambiguous invocation on types implementing both mutable and read-only interfaces. Kept: GetValueOrNull (struct, no BCL equivalent), GetOrElse (lazy factory), all TryParse methods, collection safe-access on IReadOnlyList. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/ANcpLua.Roslyn.Utilities/TryExtensions.cs | 200 +----------------- 1 file changed, 4 insertions(+), 196 deletions(-) diff --git a/src/ANcpLua.Roslyn.Utilities/TryExtensions.cs b/src/ANcpLua.Roslyn.Utilities/TryExtensions.cs index 34d9872..caed4e0 100644 --- a/src/ANcpLua.Roslyn.Utilities/TryExtensions.cs +++ b/src/ANcpLua.Roslyn.Utilities/TryExtensions.cs @@ -2,8 +2,8 @@ namespace ANcpLua.Roslyn.Utilities; /// /// Nullable-returning Try* alternatives that chain with ?. better than the BCL's bool + out shape: -/// dictionary GetOrNull/Default/Else, TryParse for every BCL numeric/bool/char/Guid/enum/DateTime*/TimeSpan, -/// and ElementAtOrNull/Default for . +/// dictionary GetValueOrNull/Else, TryParse for every BCL numeric/bool/char/Guid/enum/DateTime*/TimeSpan, +/// and ElementAtOrNull/Default for . /// #if ANCPLUA_ROSLYN_PUBLIC public @@ -12,63 +12,6 @@ namespace ANcpLua.Roslyn.Utilities; #endif static class TryExtensions { - // ========== Dictionary Extensions (Reference Types) ========== - - /// - /// Gets the value associated with the specified key, or null if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary (must be a reference type). - /// The dictionary to search. - /// The key to look up. - /// - /// The value associated with if found; otherwise, null. - /// - /// - /// - /// This method provides a cleaner alternative to TryGetValue when you just - /// need the value or null. - /// - /// - /// - /// - /// // Before - /// if (dict.TryGetValue(key, out var value)) - /// { - /// DoSomething(value); - /// } - /// - /// // After - works with null-conditional - /// dict.GetOrNull(key)?.DoSomething(); - /// - /// // Or in a chain - /// var result = dict.GetOrNull(key)?.Process(); - /// - /// - /// - public static TValue? GetOrNull(this IDictionary dictionary, TKey key) - where TValue : class - { - return dictionary.TryGetValue(key, out var value) ? value : null; - } - - /// - /// Gets the value associated with the specified key, or null if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary (must be a reference type). - /// The read-only dictionary to search. - /// The key to look up. - /// - /// The value associated with if found; otherwise, null. - /// - /// - public static TValue? GetOrNull(this IReadOnlyDictionary dictionary, TKey key) - where TValue : class - { - return dictionary.TryGetValue(key, out var value) ? value : null; - } - // ========== Dictionary Extensions (Value Types) ========== /// @@ -88,73 +31,13 @@ static class TryExtensions /// int? count = counts.GetValueOrNull("key"); /// /// - public static TValue? GetValueOrNull(this IDictionary dictionary, TKey key) - where TValue : struct - { - return dictionary.TryGetValue(key, out var value) ? value : null; - } - - /// - /// Gets the value associated with the specified key, or null if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary (must be a value type). - /// The read-only dictionary to search. - /// The key to look up. - /// - /// The value associated with wrapped in a nullable if found; - /// otherwise, null. - /// public static TValue? GetValueOrNull(this IReadOnlyDictionary dictionary, TKey key) where TValue : struct { return dictionary.TryGetValue(key, out var value) ? value : null; } - // ========== Dictionary Extensions (Default Value) ========== - - /// - /// Gets the value associated with the specified key, or a default value if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary. - /// The dictionary to search. - /// The key to look up. - /// The value to return if the key is not found. - /// - /// The value associated with if found; - /// otherwise, . - /// - /// - /// - /// var timeout = settings.GetOrDefault("Timeout", 30); - /// var name = users.GetOrDefault(userId, "Unknown"); - /// - /// - /// - public static TValue GetOrDefault(this IDictionary dictionary, TKey key, - TValue defaultValue) - { - return dictionary.TryGetValue(key, out var value) ? value : defaultValue; - } - - /// - /// Gets the value associated with the specified key, or a default value if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary. - /// The read-only dictionary to search. - /// The key to look up. - /// The value to return if the key is not found. - /// - /// The value associated with if found; - /// otherwise, . - /// - public static TValue GetOrDefault(this IReadOnlyDictionary dictionary, TKey key, - TValue defaultValue) - { - return dictionary.TryGetValue(key, out var value) ? value : defaultValue; - } + // ========== Dictionary Extensions (Lazy Factory) ========== /// /// Gets the value associated with the specified key, or computes a default using a factory if not found. @@ -163,35 +46,6 @@ public static TValue GetOrDefault(this IReadOnlyDictionaryThe type of values in the dictionary. /// The dictionary to search. /// The key to look up. - /// A factory function to compute the default value (only called if key is not found). - /// - /// The value associated with if found; - /// otherwise, the result of . - /// - /// - /// - /// Use this when the default value is expensive to compute and should only be - /// calculated when the key is not found. - /// - /// - /// - /// - /// var config = cache.GetOrElse(key, () => LoadExpensiveConfig()); - /// - /// - public static TValue GetOrElse(this IDictionary dictionary, TKey key, - Func factory) - { - return dictionary.TryGetValue(key, out var value) ? value : factory(); - } - - /// - /// Gets the value associated with the specified key, or computes a default using a factory if not found. - /// - /// The type of keys in the dictionary. - /// The type of values in the dictionary. - /// The read-only dictionary to search. - /// The key to look up. /// A factory function to compute the default value. /// /// The value associated with if found; @@ -670,21 +524,6 @@ public static TimeSpan TryParseTimeSpan(this string? value, TimeSpan defaultValu /// var last = items.ElementAtOrNull(items.Count - 1); /// /// - /// - public static T? ElementAtOrNull(this IList list, int index) where T : class - { - return index >= 0 && index < list.Count ? list[index] : null; - } - - /// - /// Gets the element at the specified index, or null if the index is out of bounds. - /// - /// The type of elements in the list. - /// The read-only list to access. - /// The zero-based index of the element to get. - /// - /// The element at if within bounds; otherwise, null. - /// public static T? ElementAtOrNull(this IReadOnlyList list, int index) where T : class { return index >= 0 && index < list.Count ? list[index] : null; @@ -700,21 +539,6 @@ public static TimeSpan TryParseTimeSpan(this string? value, TimeSpan defaultValu /// The element at wrapped in a nullable if within bounds; /// otherwise, null. /// - public static T? ValueAtOrNull(this IList list, int index) where T : struct - { - return index >= 0 && index < list.Count ? list[index] : null; - } - - /// - /// Gets the value type element at the specified index, or null if the index is out of bounds. - /// - /// The type of elements in the list (must be a value type). - /// The read-only list to access. - /// The zero-based index of the element to get. - /// - /// The element at wrapped in a nullable if within bounds; - /// otherwise, null. - /// public static T? ValueAtOrNull(this IReadOnlyList list, int index) where T : struct { return index >= 0 && index < list.Count ? list[index] : null; @@ -736,22 +560,6 @@ public static TimeSpan TryParseTimeSpan(this string? value, TimeSpan defaultValu /// var item = items.ElementAtOrDefault(index, fallbackItem); /// /// - public static T ElementAtOrDefault(this IList list, int index, T defaultValue) - { - return index >= 0 && index < list.Count ? list[index] : defaultValue; - } - - /// - /// Gets the element at the specified index, or a default value if the index is out of bounds. - /// - /// The type of elements in the list. - /// The read-only list to access. - /// The zero-based index of the element to get. - /// The value to return if the index is out of bounds. - /// - /// The element at if within bounds; - /// otherwise, . - /// public static T ElementAtOrDefault(this IReadOnlyList list, int index, T defaultValue) { return index >= 0 && index < list.Count ? list[index] : defaultValue; @@ -778,4 +586,4 @@ public static T ElementAtOrDefault(this IReadOnlyList list, int index, T d { return Base64Url.TryDecode(input, out var bytes) ? bytes : null; } -} \ No newline at end of file +}