diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 88a492f02f..f1154130ac 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -9,15 +9,16 @@ using System; using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Text; -using Google.Protobuf.Reflection; -using Google.Protobuf.WellKnownTypes; using System.IO; using System.Linq; -using System.Collections.Generic; using System.Reflection; -using System.Diagnostics.CodeAnalysis; +using System.Text; +using Google.Protobuf.Reflection; +using Google.Protobuf.WellKnownTypes; namespace Google.Protobuf { @@ -962,25 +963,17 @@ namespace Google.Protobuf // The need for this is unfortunate, as is its unbounded size, but realistically it shouldn't cause issues. private static class OriginalEnumValueHelper { - // TODO: In the future we might want to use ConcurrentDictionary, at the point where all - // the platforms we target have it. - private static readonly Dictionary> dictionaries - = new Dictionary>(); + private static readonly ConcurrentDictionary> dictionaries + = new ConcurrentDictionary>(); [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "The field for the value must still be present. It will be returned by reflection, will be in this collection, and its name can be resolved.")] internal static string GetOriginalName(object value) { - var enumType = value.GetType(); - Dictionary nameMapping; - lock (dictionaries) + Dictionary nameMapping = dictionaries.GetOrAdd(value.GetType(), static t => { - if (!dictionaries.TryGetValue(enumType, out nameMapping)) - { - nameMapping = GetNameMapping(enumType); - dictionaries[enumType] = nameMapping; - } - } + return GetNameMapping(t); + }); // If this returns false, originalName will be null, which is what we want. nameMapping.TryGetValue(value, out string originalName);