C#Strings(和其他.NET API)的大小限制为2GB吗?

时间:2010-06-24 02:52:29

标签: c# .net visual-studio string

今天我注意到C#的String类将字符串的长度作为Int返回。由于Int总是32位,无论架构如何,这是否意味着字符串的长度只能是2GB或更少?

一个2GB的字符串会非常不寻常,并且会出现很多问题。但是,大多数.NET api似乎都使用'int'来传达长度和计数等值。这是否意味着我们永远受限于适合32位的集合大小?

似乎是.NET API的一个基本问题。我希望通过相当于'size_t'的方式返回count和length之类的东西。

8 个答案:

答案 0 :(得分:16)

  

似乎是一个根本问题   .NET API ......

我不知道我是否会走得那么远。

考虑几乎所有.NET中的集合类。它有一个Count属性可返回int。因此,这表明该类的大小为int.MaxValue(2147483647)。这不是一个问题;这是一个限制 - 在绝大多数场景中都是一个非常合理的限制。

无论如何,替代方案是什么?有uint - 但这不符合CLS。然后是long ...

如果Length返回long

,该怎么办?
  1. 如果您想知道字符串的长度,则需要额外的32位内存。
  2. 好处是:我们可以让字符串占用数十亿GB的RAM。万岁。
  3. 试着想象一下像这样的代码令人难以置信的代价:

    // Lord knows how many characters
    string ulysses = GetUlyssesText();
    
    // allocate an entirely new string of roughly equivalent size
    string schmulysses = ulysses.Replace("Ulysses", "Schmulysses");
    

    基本上,如果您认为string是一种旨在存储无限量文本的数据结构,那么您就会有不切实际的期望。当涉及到这种大小的对象时,你是否有必要将它们保存在内存中(而不是硬盘)是值得怀疑的。

答案 1 :(得分:5)

正确,最大长度将是Int32的大小,但如果您处理的字符串大于此值,则可能会遇到其他内存问题。

答案 2 :(得分:3)

在String.length()的某个值可能大约为5MB时,再也不能使用String了。字符串针对短文本进行了优化。

想想当你做什么时会发生什么

msString += " more chars"

类似的东西:

系统计算myString的长度加上“more chars”的长度

系统分配该内存量

系统将myString复制到新的内存位置

系统在上次复制myString char后将“更多字符”复制到新的内存位置

原始的myString受垃圾收集器的支配。

虽然这对于一小段文本来说是好的和整洁的,但对于大字符串来说却是一场噩梦,只需找到2GB的连续内存就可能是一个显而易见的事。

因此,如果您知道处理超过几MB的字符,请使用其中一个* Buffer类。

答案 3 :(得分:1)

您不太可能需要在单个集合中存储超过20亿个对象。在进行枚举和查找时,您将会遇到一些非常严重的性能损失,这是集合的两个主要目的。如果您正在处理的数据集很大,那么您可以采取其他一些路径,例如将您的单个集合拆分为许多较小的集合,这些集合包含您正在使用的整个数据集的部分。

Heeeey,等一下......我们已经有了这个概念 - 它被称为字典

如果您需要存储50亿英文字符串,请使用以下类型:

Dictionary<string, List<string>> bigStringContainer;

让我们让关键字符串代表字符串的前两个字符。然后编写一个这样的扩展方法:

public static string BigStringIndex(this string s)
{
    return String.Concat(s[0], s[1]);
}

然后将项目添加到bigStringContainer,如下所示:

bigStringContainer[item.BigStringIndex()].Add(item);

并称之为一天。 (显然有更有效的方法可以做到这一点,但这只是一个例子)

哦,如果你确实真的需要能够通过绝对索引查找任意对象,请使用Array而不是集合。好的是,您使用了某种类型的安全性,但您可以使用long索引数组元素。

答案 4 :(得分:1)

框架对Int32 / Count属性,索引器等使用Length这一事实有点像红色鲱鱼。真正的问题是CLR目前的最大对象大小限制为2GB。

所以string - 或任何其他单个对象 - 永远不会超过2GB。

更改Length类型的string属性以返回longulong甚至BigInteger将毫无意义,因为您永远不会超过约无论如何2 ^ 30个字符(最大2GB,每个字符2个字节。)

同样,由于2GB的限制,唯一可以接近2 ^ 31个元素的数组将是bool[]byte[]个数组,每个元素只使用1个字节。

当然,没有什么可以阻止你创建自己的复合类型来解决2GB限制。

(请注意,上述观察结果适用于Microsoft当前的实施,并且在未来版本中可能会发生很大变化。我不确定Mono是否有类似的限制。)

答案 5 :(得分:1)

在4.5之前的.NET版本中,最大对象大小为2GB。从4.5开始,如果启用gcAllowVeryLargeObjects,您可以分配更大的对象。请注意,string的限制不受影响,但“数组”也应该包含“列表”,因为列表由数组支持。

答案 6 :(得分:0)

即使在x64版本的Windows中,我也被.Net限制,将每个对象限制为2GB。

对于医学影像而言,2GB相当小。对于Visual Studio下载映像,2GB甚至很小。

答案 7 :(得分:-1)

如果您使用的是2GB的文件,这意味着您可能会使用大量内存,而且您的性能会非常慢。

相反,对于非常大的文件,请考虑使用MemoryMappedFile(请参阅:http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx)。使用此方法,您可以使用几乎无限大小的文件,而无需将整个内容加载到内存中。