当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《C#:具有相同内容的字符串》经验,为你挑选了2个好方法。

我听过并读过一个字符串无法更改(不可变?).我想这应该是正确的.但我也听说过两个内容相同的字符串共享相同的内存空间(或者你称之为内存空间).它是否正确?

如果是这样,这是否意味着如果我创建一个包含数千个字符串的List,如果大多数字符串彼此相等,那么根本不会占用太多空间?



1> Jon Skeet..:

编辑:在下面的答案中,我将实习池称为AppDomain特定的; 我很确定这是我之前观察到的,但是String.Intern的MSDN文档表明整个过程都有一个实习池,这使得它更加重要.

原始答案

(我打算将此作为评论添加,但我认为这是一个非常重要的一点,需要额外的答案......)

正如其他人所解释的那样,字符串实习发生在所有字符串文字中,但不在"动态创建"字符串上(例如从数据库或文件中读取的字符串,或使用StringBuilder或构建的字符串String.Format).

但是,我建议打电话String.Intern来绕过后一点:它会在你的生命周期中AppDomain填充实习池.相反,请使用仅限于您的使用的本地池.以下是此类池的示例:

public class StringPool
{
    private readonly Dictionary contents =
        new Dictionary();

    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),但是您不会污染"全局"资源(实习池).


@CB:是的-我想要这个值。当TryGetValue在一个操作中同时执行两次操作时,为什么要通过ContainsKey和索引器两次查询呢?

2> Teun D..:

这或多或少是真的.它被称为"字符串实习".字符串文字只在内存中出现一次,设置为相同值的每个变量都指向此单个表示.但是,代码中创建的字符串不会自动实现.

http://msmvps.com/blogs/manoj/archive/2004/01/09/1549.aspx

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有