代码之家  ›  专栏  ›  技术社区  ›  Neil C. Obremski

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

  •  4
  • Neil C. Obremski  · 技术社区  · 16 年前

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

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

    不可变,但这并不意味着函数总是必须返回一个新函数,而是意味着任何东西都不能更改其字符内容。

    4 回复  |  直到 16 年前
        1
  •  11
  •   Marc Gravell    16 年前

    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);
    
        2
  •  4
  •   cgreeno    16 年前

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

        3
  •  2
  •   Peter Å tibraný    16 年前

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

        4
  •  1
  •   Joel Coehoorn    16 年前

    [编辑]
    Interning

        5
  •  0
  •   rollsch    4 年前

    如果使用以下代码,它将不会分配新内存,并将覆盖原始字符串(这可能是您想要的,也可能不是您想要的)。它需要一个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%,并避免了内存分配。

    我只会在紧循环中经常使用100000或更多字符串的情况下使用这种方法。