Skip to content

Commit 88caa25

Browse files
committed
Avoid repeat allocations in Enum.TryParse
1 parent d97bdbe commit 88caa25

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

StyleCop.Analyzers/StyleCop.Analyzers/Settings/JsonHelper.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace StyleCop.Analyzers
77
{
88
using System;
99
using System.Collections.Generic;
10+
using System.Collections.Immutable;
1011
using LightJson;
1112

1213
/// <summary>
@@ -82,15 +83,15 @@ internal static string ToStringValue(this JsonValue jsonValue, string elementNam
8283
/// <param name="jsonValue">The key value pair identifying the JSON value.</param>
8384
/// <returns>The enum value contained within the JSON value.</returns>
8485
internal static TEnum ToEnumValue<TEnum>(this KeyValuePair<string, JsonValue> jsonValue)
85-
where TEnum : struct
86+
where TEnum : struct, Enum
8687
{
8788
if (!jsonValue.Value.IsString)
8889
{
8990
throw new InvalidSettingsException($"{jsonValue.Key} must contain an enum (string) value");
9091
}
9192

9293
TEnum result;
93-
if (!Enum.TryParse(jsonValue.Value.AsString, true, out result))
94+
if (!EnumHelper<TEnum>.TryParse(jsonValue.Value.AsString, out result))
9495
{
9596
throw new InvalidSettingsException($"{jsonValue.Key} cannot contain enum value '{jsonValue.Value.AsString}'");
9697
}
@@ -106,15 +107,15 @@ internal static TEnum ToEnumValue<TEnum>(this KeyValuePair<string, JsonValue> js
106107
/// <param name="elementName">The element name to report in exceptions.</param>
107108
/// <returns>The enum value contained within the JSON value.</returns>
108109
internal static TEnum ToEnumValue<TEnum>(this JsonValue jsonValue, string elementName)
109-
where TEnum : struct
110+
where TEnum : struct, Enum
110111
{
111112
if (!jsonValue.IsString)
112113
{
113114
throw new InvalidSettingsException($"{elementName} must contain an enum (string) value");
114115
}
115116

116117
TEnum result;
117-
if (!Enum.TryParse(jsonValue.AsString, true, out result))
118+
if (!EnumHelper<TEnum>.TryParse(jsonValue.AsString, out result))
118119
{
119120
throw new InvalidSettingsException($"{elementName} cannot contain enum value '{jsonValue.AsString}'");
120121
}
@@ -145,5 +146,25 @@ internal static void AssertIsObject(this KeyValuePair<string, JsonValue> jsonVal
145146
throw new InvalidSettingsException($"{jsonValue.Key} must contain an object");
146147
}
147148
}
149+
150+
private static class EnumHelper<TEnum>
151+
where TEnum : struct, Enum
152+
{
153+
private static ImmutableDictionary<string, KeyValuePair<bool, TEnum>> values = ImmutableDictionary<string, KeyValuePair<bool, TEnum>>.Empty;
154+
155+
public static bool TryParse(string value, out TEnum result)
156+
{
157+
var successAndResult = ImmutableInterlocked.GetOrAdd(
158+
ref values,
159+
value,
160+
static value =>
161+
{
162+
bool success = Enum.TryParse(value, true, out TEnum result);
163+
return new KeyValuePair<bool, TEnum>(success, result);
164+
});
165+
result = successAndResult.Value;
166+
return successAndResult.Key;
167+
}
168+
}
148169
}
149170
}

0 commit comments

Comments
 (0)