From d540b04cc4c37cfbc3ef60fc79aca92655a5b249 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 14 Oct 2022 15:20:05 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E7=B4=A0=E7=9B=B4=E3=81=AA=20static=20type?= =?UTF-8?q?=20caching=20=E6=8A=80=E6=B3=95=E3=81=AB=E3=81=AA=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E6=9B=B8=E3=81=8D=E7=9B=B4=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/Utils/CachedEnum/CachedEnum.cs | 15 ++++- .../Utils/CachedEnum/CachedEnumType.cs | 56 +++++++++---------- Assets/UniGLTF/Tests/UniGLTF/CacheEnumTest.cs | 4 +- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs index 7bf4bd131..8704dc0d0 100644 --- a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs +++ b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs @@ -2,11 +2,22 @@ namespace UniGLTF.Utils { + /// + /// CachedEnumType に対するインターフェース。 + /// 非 Generic class + /// public static class CachedEnum { public static T Parse(string name, bool ignoreCase = false) where T : struct, Enum { - return CachedEnumType.Parse(name, ignoreCase); + if (ignoreCase) + { + return CachedEnumType.IgnoreCaseMap[name]; + } + else + { + return CachedEnumType.Map[name]; + } } public static T TryParseOrDefault(string name, bool ignoreCase = false, T defaultValue = default) @@ -16,7 +27,7 @@ namespace UniGLTF.Utils { return Parse(name, ignoreCase: ignoreCase); } - catch + catch (System.Collections.Generic.KeyNotFoundException) { return defaultValue; } diff --git a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs index 8133d2a8e..dc297b3f8 100644 --- a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs +++ b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs @@ -3,41 +3,37 @@ using System.Collections.Generic; namespace UniGLTF.Utils { + /// + /// enum T に対する static type caching 。 + /// + /// CachedEnumType.Values + /// CachedEnumType.Map + /// CachedEnumType.IgnoreCaseMap + /// + /// がスレッドセーフに(キャッシュされた)同じ値を返す。 + /// internal static class CachedEnumType where T : struct, Enum { - private static readonly Dictionary _values = new Dictionary(); - private static readonly Dictionary _ignoreCaseValues = new Dictionary(StringComparer.OrdinalIgnoreCase); - private static T[] _allValues; + public readonly static Dictionary Map = CreateStringEnumMap(false); + public readonly static Dictionary IgnoreCaseMap = CreateStringEnumMap(true); + public readonly static T[] Values = (T[])Enum.GetValues(typeof(T)); - public static T[] Values + private static Dictionary CreateStringEnumMap(bool ignoreCase) { - get + var dict = ignoreCase + ? new Dictionary(StringComparer.OrdinalIgnoreCase) + : new Dictionary() + ; + + // ここで Values を使うと + // System.TypeInitializationException + // が起きる。 + // static 変数初期化中に別の static 変数を参照すると未初期化がありえるぽい(初期化順?) + foreach (T value in Enum.GetValues(typeof(T))) { - if (_allValues == null) - { - _allValues = Enum.GetValues(typeof(T)) as T[]; - } - - return _allValues; + dict.Add(value.ToString(), value); } - } - - public static T Parse(string name, bool ignoreCase) - { - var caches = ignoreCase ? _ignoreCaseValues : _values; - - if (caches.TryGetValue(name, out var ignoreCaseValue)) - { - return ignoreCaseValue; - } - - if (Enum.TryParse(name, ignoreCase, out var result)) - { - caches.Add(name, result); - return result; - } - - throw new ArgumentException(name); + return dict; } } -} \ No newline at end of file +} diff --git a/Assets/UniGLTF/Tests/UniGLTF/CacheEnumTest.cs b/Assets/UniGLTF/Tests/UniGLTF/CacheEnumTest.cs index e14ee7919..2018c00ee 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/CacheEnumTest.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/CacheEnumTest.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System.Linq; +using NUnit.Framework; using UniGLTF.Utils; using UnityEngine; @@ -12,6 +13,7 @@ namespace UniGLTF { Assert.AreEqual(default(HumanBodyBones), CachedEnum.TryParseOrDefault("xxx")); Assert.AreEqual(HumanBodyBones.UpperChest, CachedEnum.TryParseOrDefault("upperchest", true)); + Assert.AreEqual(CachedEnum.GetValues().First(x => x == HumanBodyBones.Hips), HumanBodyBones.Hips); } } } From 2b0d003ab59de079b64a4737b54630c9f84e29ef Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 14 Oct 2022 15:42:28 +0900 Subject: [PATCH 2/3] =?UTF-8?q?TryParseOrDefault=20=E3=81=8C=20Try=20?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=AA=E3=81=84=E3=81=AE=E3=81=A7=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E5=90=8D=E3=82=92=E5=A4=89=E3=81=88=E3=82=8B=E6=84=8F?= =?UTF-8?q?=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs index 8704dc0d0..05322b2fd 100644 --- a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs +++ b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnum.cs @@ -20,7 +20,7 @@ namespace UniGLTF.Utils } } - public static T TryParseOrDefault(string name, bool ignoreCase = false, T defaultValue = default) + public static T ParseOrDefault(string name, bool ignoreCase = false, T defaultValue = default) where T : struct, Enum { try @@ -33,6 +33,16 @@ namespace UniGLTF.Utils } } + /// + /// bool を返して out 変数に結果を返すのが TryXXX なので、Try ではない。 + /// + [Obsolete("use ParseOrDefault")] + public static T TryParseOrDefault(string name, bool ignoreCase = false, T defaultValue = default) + where T : struct, Enum + { + return ParseOrDefault(name, ignoreCase: ignoreCase); + } + public static T[] GetValues() where T : struct, Enum { return CachedEnumType.Values; From 66092a43643f73632c19f0265055b746965671b5 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Oct 2022 15:30:42 +0900 Subject: [PATCH 3/3] readonly field to get only property --- Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs index dc297b3f8..e840e4341 100644 --- a/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs +++ b/Assets/UniGLTF/Runtime/Utils/CachedEnum/CachedEnumType.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; + namespace UniGLTF.Utils { /// @@ -14,9 +15,9 @@ namespace UniGLTF.Utils /// internal static class CachedEnumType where T : struct, Enum { - public readonly static Dictionary Map = CreateStringEnumMap(false); - public readonly static Dictionary IgnoreCaseMap = CreateStringEnumMap(true); - public readonly static T[] Values = (T[])Enum.GetValues(typeof(T)); + public static IReadOnlyDictionary Map { get; } = CreateStringEnumMap(false); + public static IReadOnlyDictionary IgnoreCaseMap { get; } = CreateStringEnumMap(true); + public static T[] Values { get; } = (T[])Enum.GetValues(typeof(T)); private static Dictionary CreateStringEnumMap(bool ignoreCase) {