しばらく前 (私が足を踏み外したとき)に、リソース文字列を使用した場合のパフォーマンス オーバーヘッドに関して、リソース ファイル (.resx) を使用した場合のパフォーマンス オーバーヘッドについて次の質問をしました。私は賛成票を投じた回答を得て、その回答を正しいものとしました。ただし、以前は、エラー状態で呼び出され、パフォーマンスが重要ではないメッセージ文字列をローカライズしていました。現在は、コード「パワーハウス」(多くのパフォーマンスが重要なコード、組み込みループなど) にローカライズを実装するよう求められています。
これをさらに詳しく調べる時間があり、次のようなリソースを呼び出すことに気付きました
Resources.MessageStrings.SomeResourceName
MessageStrings.Designer.cs
を使用する自動生成コードへの呼び出しを参照するだけです。
internal static string SomeResourceName {
get {
return ResourceManager.GetString("SomeResourceName", resourceCulture);}
}
深く掘り下げて、次の場所にあるものを逆コンパイルすると思いResourceManager
ました
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\mscorlib.dll
何GetString()
が行われていたかを確認するには [リソース文字列を本当にキャッシュしていますか? ]。逆コンパイル、私は見つけます
[__DynamicallyInvokable]
public virtual string GetString(string name, CultureInfo culture)
{
if (name == null)
throw new ArgumentNullException("name");
if (ResourceManager.s_IsAppXModel && object.ReferenceEquals((object) culture, (object) CultureInfo.CurrentUICulture))
culture = (CultureInfo) null;
if (this._bUsingModernResourceManagement)
{
if (this._PRIonAppXInitialized)
return this.GetStringFromPRI(name, culture == null ? (string) null : culture.Name, this._neutralResourcesCulture.Name);
if (this._PRIExceptionInfo == null || this._PRIExceptionInfo._PackageSimpleName == null || this._PRIExceptionInfo._ResWFile == null)
throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoPRIresources"));
throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_ResWFileNotLoaded", (object) this._PRIExceptionInfo._ResWFile, (object) this._PRIExceptionInfo._PackageSimpleName));
}
else
{
if (culture == null)
culture = Thread.CurrentThread.GetCurrentUICultureNoAppX();
if (FrameworkEventSource.IsInitialized)
FrameworkEventSource.Log.ResourceManagerLookupStarted(this.BaseNameField, this.MainAssembly, culture.Name);
ResourceSet resourceSet1 = this.GetFirstResourceSet(culture);
if (resourceSet1 != null)
{
string @string = resourceSet1.GetString(name, this._ignoreCase);
if (@string != null)
return @string;
}
foreach (CultureInfo culture1 in new ResourceFallbackManager(culture, this._neutralResourcesCulture, true))
{
ResourceSet resourceSet2 = this.InternalGetResourceSet(culture1, true, true);
if (resourceSet2 != null)
{
if (resourceSet2 != resourceSet1)
{
string @string = resourceSet2.GetString(name, this._ignoreCase);
if (@string != null)
{
if (this._lastUsedResourceCache != null)
{
lock (this._lastUsedResourceCache)
{
this._lastUsedResourceCache.lastCultureName = culture1.Name;
this._lastUsedResourceCache.lastResourceSet = resourceSet2;
}
}
return @string;
}
else
resourceSet1 = resourceSet2;
}
}
else
break;
}
if (FrameworkEventSource.IsInitialized)
FrameworkEventSource.Log.ResourceManagerLookupFailed(this.BaseNameField, this.MainAssembly, culture.Name);
return (string) null;
}
}
上記のコードには、文字列を「キャッシュ」していることを示唆するものは何もありません (典型的/真の意味で)。何らかのタイプの複雑な検索を行っているようです。メソッドが文書化されていない属性を使用していることに気付き、__DynamicallyInvokable
Hans によるこの属性の簡単な説明を見つけました ( __DynamicallyInvokable 属性は何のためのものですか? )。
私の質問は次のとおりです。パフォーマンスが重要なコードの場合、十分に高速であることを信頼できますか (文字列をキャッシュしますか? )、またはリソース文字列を自分で前処理してキャッシュする必要がありますか?ResourceManager
御時間ありがとうございます。