C#:具有相同内容的字符串

标签 c# string

我听说和读到一个字符串不能改变(不可变的?)。我想那应该是正确的。但我也听说两个内容相同的字符串共享相同的内存空间(或你所说的)。这是正确的吗?

如果是这样,这是否意味着如果我创建一个包含数千个字符串的列表,如果其中大多数字符串彼此相等,它实际上根本不会占用太多空间?

最佳答案

编辑:在下面的回答中,我将实习生池称为特定于 AppDomain 的;我很确定这就是我之前观察到的,但是 String.Intern 的 MSDN 文档建议整个过程只有一个实习生池,这使这一点变得更加重要。

原始答案

(我本来打算将其添加为评论,但我认为这是一个足够重要的点,需要一个额外的答案......)

正如其他人所解释的那样,字符串驻留发生在所有字符串文字上,但不会发生在“动态创建”的字符串上(例如,从数据库或文件中读取的字符串,或者使用 StringBuilderString.Format 构建的字符串。)

但是,我不会建议调用 String.Intern绕过后一点:它将在你的 AppDomain 的生命周期内填充实习生池 。相反,使用仅供您使用的本地池。这是此类池的示例:

public class StringPool
{
    private readonly Dictionary<string,string> contents =
        new Dictionary<string,string>();

    public string Add(string item)
    {
        string ret;
        if (!contents.TryGetValue(item, out ret))
        {
            contents[item] = item;
            ret = item;
        }
        return ret;
    }
}

然后你只需使用类似的东西:

string data = pool.Add(ReadItemFromDatabase());

(请注意,池不是线程安全的;正常使用不需要它。)

这样一来,您就可以在不再需要时立即丢弃您的池,而不是永远在内存中保留大量潜在的字符串。你也可以让它更聪明,实现 LRU 缓存或者如果你真的想要的话。

编辑:只是为了阐明为什么这比使用 String.Intern 更好... 假设您从数据库或日志文件中读取了一堆字符串,对其进行处理,然后转到另一项任务。如果您调用 String.Intern在这些字符串上,只要您的 AppDomain 存在,它们永远不会被垃圾回收还活着-甚至可能还活着。如果您加载多个不同的日志文件,您将在您的实习生池中逐渐积累字符串,直到您完成或耗尽内存。相反,我建议采用这样的模式:

void ProcessLogFile(string file)
{
    StringPool pool = new StringPool();
    // Process the log file using strings in the pool
} // The pool can now be garbage collected

在这里,您可以获得同一个文件中的多个字符串在内存中只存在一次的好处(或者至少,只超过 gen0 一次),但您不会污染“全局”资源(实习生池)。

关于C#:具有相同内容的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/555871/

相关文章:

c# - 在 Web API 响应中添加 zip 文件作为内容,下载时文件大小加倍

sql - 将数字转换为单词-第一,第二,第三等

Javascript-向数组字符串添加换行符

c# - 如何在unity inspector中制作折线图

java - 输入磁盘文件并将其存储为字符串和整数

java - 如何在java中使用正则表达式从下面的字符串中获取值

mysql - 如何删除Mysql列中的多个字符串

c# - 遍历目录中的子目录

c# - 使用 c# 在静默模式下安装 MS Outlook 2010

c# - 在 where() 方法上使用 for 循环