使用资源文件(.resx)时的性能开销

16
请注意,我已经了解了关于这个主题的以下问题:
  1. 有关资源(.resx)文件是否存在性能问题或注意事项?

  2. 字符串资源(.resx)属性是否保存在内存中?

然而,我发现这些问题的答案都不够具体。我还知道有关此主题的MSDN页面,但是它们似乎也缺乏关于使用资源文件的开销的技术信息。
我所面临的问题是,我们即将开始对一个相当大的WinForms应用程序进行本地化。我目前担心的是从嵌套循环中访问.resx文件中的资源的性能问题。目前,对于我们已本地化的代码的一小部分(如DataGridView的列名、行标头等),我们将资源缓存到相关类的全局变量中并使用它们。
如何访问.resx中的资源(它们是否在编译时包含在程序集中?)并且是否有性能优势可以将这些资源缓存并使用全局变量进行访问?
1个回答

19

字符串资源被缓存在内存中。查看在 "Resources.Designer.cs" 文件中生成的代码。

它使用了 System.Resources.ResourceManager,并且它会对字符串进行缓存。

还要注意 这个 ResourceManager 构造函数。它提到您可以更改缓存策略:

此构造函数使用系统提供的 ResourceSet 实现。要使用自定义的资源文件格式,您应该从 ResourceSet 类派生,重写 GetDefaultReader 和 GetDefaultWriter 方法,并将该类型传递给 ResourceManager(String, Assembly, Type) 构造函数。使用自定义 ResourceSet 可以有助于控制资源缓存策略或支持您自己的资源文件格式,但通常不是必需的。

(强调为本人添加)

ResourceSet 的文档明确表示:

ResourceSet 类枚举 IResourceReader,加载每个名称和值,并将它们存储在 Hashtable 中。

所以我们确切地了解默认情况下会得到哪种缓存策略。

[编辑] 由于您似乎不相信我! :)

(1) 查看构造函数 ResourceManager(string baseName,Assembly assembly) 的文档。它说明:

此构造函数使用系统提供的 ResourceSet 实现。

(2) 现在查看 ResourceSet 的文档。它说明:

ResourceSet类枚举IResourceReader中的所有名称和值,并将它们存储在Hashtable中,从而实现缓存行为。

因此,MSDN确实记录了这种缓存行为,并且您可以使用Resharper检查实现以验证这就是正在发生的事情。


+1 非常感谢您的回复。非常感激。您能为我解释另一件事吗?从MSDN文档调用资源,我们可以使用ResourceManager rm = new ResourceManager("ExampleResources", typeof(Example).Assembly); string greeting = rm.GetString("Greeting");,但我从https://dev59.com/AnM_5IYBdhLWcg3w-4hg#1142840了解到,这也可以通过`Console.WriteLine(strings.Hello);`来完成,其中资源文件是`strings.resx`。有什么区别? - MoonKnight
你能帮忙解决这个问题吗:http://stackoverflow.com/questions/15523604/error-in-generation-of-resource-resource-design-cs-file - MoonKnight
1
使用 strings.Hello 只是在使用 Resources.Designer.cs 中自动生成的类。 - Matthew Watson
我仍然不确定字符串的缓存。如果您查看Design.cs文件,给定资源的属性调用GetString(...),在我看来,这似乎并没有缓存字符串,而是在运行时从资源文件中检索它们...此外,MSDN文档也没有提到缓存。 - MoonKnight
1
它调用 ResourceManager.GetString(),最终调用 ResourceSet.GetString(),该方法调用 ResourceSet.GetObjectInternal(),后者在哈希表中查找字符串。您可以通过检查Resharper中的代码来验证此操作。MSDN文档确实提到了缓存,并且我在上面的答案中提供了引用。 - Matthew Watson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接