String.ToLower()总是分配内存吗?

时间:2009-02-02 21:19:54

标签: c# .net string lowercase

如果所有字符都已小写,String.ToLower()是否会返回相同的引用(例如,不分配任何新内存)?

内存分配很便宜,但快速检查数以万计的短字符串甚至更便宜。大部分时间我正在使用的输入已经是小写的,但如果不是这样的话,我想这样做。

我特别使用C#/ .NET,但我的好奇心延伸到其他语言,所以请随意回答你最喜欢的语言!

注意:字符串 是不可变的,但这并不意味着函数总是必须返回一个新函数,而是意味着什么都不能改变它们的字符内容。

5 个答案:

答案 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 个或更多的字符串,我只会使用这样的东西。