From d540b04cc4c37cfbc3ef60fc79aca92655a5b249 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 14 Oct 2022 15:20:05 +0900 Subject: [PATCH] =?UTF-8?q?=E7=B4=A0=E7=9B=B4=E3=81=AA=20static=20type=20c?= =?UTF-8?q?aching=20=E6=8A=80=E6=B3=95=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88?= =?UTF-8?q?=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); } } }