5

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

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

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

注意:字符串不可变的,但这并不意味着函数总是必须返回一个新的,而是意味着没有任何东西可以改变它们的字符内容。

4

5 回答 5

11

我希望如此,是的。快速测试同意(但这不是证据):

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);
于 2009-02-02T21:26:33.603 回答
4

字符串是不可变的。String.ToLower() 将始终返回新实例,从而在每次 ToLower() 调用时生成另一个实例。

于 2009-02-02T21:24:30.270 回答
2

Sun 的 String.toLowerCase() 的 Java 实现实际上并不总是分配新的字符串。它检查是否所有字符都是小写的,如果是,则返回原始字符串。

于 2009-02-02T21:29:01.897 回答
1

[编辑]
实习无济于事——请参阅对此答案的评论。

于 2009-02-02T21:39:04.873 回答
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 或更多的字符串,我只会使用这样的东西。

于 2021-06-29T05:56:23.217 回答