【问题标题】:Dictionary<string,T>(StringComparer) vs Dictionary<string,T> and storing key.ToUpper : Which one should you prefer?Dictionary<string,T>(StringComparer) vs Dictionary<string,T> 并存储 key.ToUpper :您应该更喜欢哪一个?
【发布时间】:2011-02-10 23:23:25
【问题描述】:

免责声明:也许是微 YAGNI 优化,但请听我说 ..

问题在于实现不区分大小写查找表。

  • 我的老方法:在填充字典时,在插入之前将键大写。当有人为您提供查找键时,将键大写。
  • 新方法(我今天了解了):字典接受了一个 IComparer 实现,所以我可以传入StringComparer.InvariantCultureIgnoreCase。我认为它会委托给 String.Compare(x, y, SomeIgnoreCaseEnum)

新方法的优势在于我不需要确保在对字典进行查找的 n 个位置中的每一个位置都执行 .ToUpper() 。

我的问题是哪一个更有效?我猜只是好奇......

更新:注意我不需要知道插入的原始密钥。此外,使用的密钥与文化无关。

【问题讨论】:

  • 编写自己的微基准测试(运行每种类型 100,000 次,计时 3 次以考虑可变条件)。
  • 记住一点。如果您在某些时候需要原始形式的密钥(例如用于打印),第一个选项不是最佳选择。
  • @Brian - 是的,我忘了把它放进去。我的用例不区分大小写且与文化无关。
  • 与文化无关,我会使用StringComparer.OrdinalIgnoreCase
  • 还可以查看这篇文章,它表明在创建 Dictionary 对象时使用比较器可以提高性能。 dotnetperls.com/dictionary-stringcomparer

标签: .net dictionary case-insensitive


【解决方案1】:

可能大写会更有效,因为它可以进行序数比较......但我非常怀疑这对你来说是一个性能瓶颈。与以往一样,在根据性能提交代码更改之前进行概要分析。

最终,指定字符串比较:

  • 意味着您无需小心使用字典的方式
  • 表示原始外壳保留在密钥中,在某些情况下有助于诊断
  • 预先明确说明您希望如何处理密钥。您最终只会在创建时声明一次 - 这会导致 IMO 代码更清晰。

【讨论】:

  • 是的。不值得到处做 ToUpper() 的麻烦。
【解决方案2】:

检查此entry。今天仍然有效。

摘录:来自 MSDN 的“New Recommendations for Using Strings in Microsoft .NET 2.0

【讨论】:

  • 该页面上的第 4 个和第 5 个 DO 让我感到困惑 - 他们推荐什么? “语言相关”是什么意思?
  • 他们更详细地解释它:msdn.microsoft.com/en-us/library/…
【解决方案3】:

我不知道性能,但我更喜欢 StringComparer 选项。使用 ToUpper,您会丢失信息(原始大小写)。确实,您可能不需要它,但有一天您可能会需要它,而且感觉不需要再做任何工作来保留它(因此不受 YAGNI 原则的影响)。

我也有一天会忘记给 ToUpper 打电话,陷入一个受伤的世界。但是我的单元测试当然会救我。

【讨论】:

  • 完全正确。我有单元测试——所以在一个地方忘记它不会伤害太久。直到下一次测试运行。
【解决方案4】:

我会接受 Oded 的“Go profile!”评论 :) 这是一个显而易见的建议。

来自我的测试 (source code here)

对于 1M ContainsKey 查找,

  • ToUpper 方法:1123 毫秒
  • 字典(OrdinalIgnoreCaseComparer) : 971 毫秒

我发现 Dictionary 带有注入的 Comparer 选项可以更好地执行且更少麻烦。所以对我来说不再有 ToUpper() 了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2013-11-26
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    相关资源
    最近更新 更多