如果所有字符都已小写,String.ToLower()
是否会返回相同的引用(例如,不分配任何新内存)?
内存分配很便宜,但快速检查数以万计的短字符串甚至更便宜。大部分时间我正在使用的输入已经是小写的,但如果不是这样的话,我想这样做。
我特别使用C#/ .NET,但我的好奇心延伸到其他语言,所以请随意回答你最喜欢的语言!
注意:字符串 是不可变的,但这并不意味着函数总是必须返回一个新函数,而是意味着什么都不能改变它们的字符内容。
答案 0 :(得分:10)
我希望如此,是的。快速测试同意(但这不是证据):
string a = "abc", b = a.ToLower();
bool areSame = ReferenceEquals(a, b); // false
一般情况下,尝试使用符合您需要的比较器。例如,如果您需要不区分大小写的字典,请使用以下字典:
var lookup = new Dictionary<string, int>(
StringComparer.InvariantCultureIgnoreCase);
同样地:
bool ciEqual = string.Equals("abc", "ABC",
StringComparison.InvariantCultureIgnoreCase);
答案 1 :(得分:4)
String是不可变的。 String.ToLower()将始终返回新实例,从而在每个ToLower()调用上生成另一个实例。
答案 2 :(得分:2)
来自Sun的String.toLowerCase()的Java实现实际上并不总是分配新的String。它检查所有字符是否都是小写,如果是,则返回原始字符串。
答案 3 :(得分:1)
[编辑]
Interning没有帮助 - 请参阅此答案的评论。
答案 4 :(得分:0)
如果您使用以下代码,它将不会分配新内存,而是会覆盖原始字符串(这可能是您想要的,也可能不是)。它需要一个 ascii 字符串。如果您对从您无法控制的函数返回的字符串调用它,预计会发生奇怪的事情。
public static unsafe void UnsafeToLower(string asciiString)
{
fixed (char* pstr = asciiString)
{
for(char* p = pstr; *p != 0; ++p)
*p = (*p > 0x40) && (*p < 0x5b) ? (char)(*p | 0x60) : (*p);
}
}
它占用了 ToLowerInvariant 的大约 25% 的时间并且避免了内存分配。
如果你在一个紧密的循环中经常说 100,000 个或更多的字符串,我只会使用这样的东西。