C# C字符串(和其他.NET API)的大小是否限制为2GB?

C# C字符串(和其他.NET API)的大小是否限制为2GB?,c#,.net,visual-studio,string,C#,.net,Visual Studio,String,今天我注意到C#的String类将字符串的长度作为Int返回。由于Int总是32位,无论采用何种体系结构,这是否意味着字符串的长度只能为2GB或更短 2GB的字符串将是非常不寻常的,并且会带来许多问题。然而,大多数.NETAPI似乎使用“int”来传递长度和计数等值。这是否意味着我们永远只限于适合32位的集合大小 似乎是.NETAPI的一个根本问题。我希望通过“size\t”的等价项返回count和length等内容。正确,最大长度是Int32的大小,但是如果处理的字符串大于此值,则可能会遇到其

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

2GB的字符串将是非常不寻常的,并且会带来许多问题。然而,大多数.NETAPI似乎使用“int”来传递长度和计数等值。这是否意味着我们永远只限于适合32位的集合大小


似乎是.NETAPI的一个根本问题。我希望通过“size\t”的等价项返回count和length等内容。

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

似乎是一个基本的问题 NET API

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

考虑一下.NET中几乎所有的集合类。很可能它有一个
Count
属性,返回一个
int
。因此,这表明该类的大小为
int.MaxValue
(2147483647)。这不是一个真正的问题;这是一个限制——在绝大多数情况下,这是一个完全合理的限制

无论如何,另一种选择是什么?有
uint
——但这不符合CLS。然后是
long

如果
Length
返回了
long
,该怎么办

  • 如果您想知道字符串的长度,则需要额外的32位内存
  • 这样做的好处是:我们可以让字符串占用数十亿GB的RAM。万岁
  • 试着想象一下这样一些代码的惊人成本:

    // Lord knows how many characters
    string ulysses = GetUlyssesText();
    
    // allocate an entirely new string of roughly equivalent size
    string schmulysses = ulysses.Replace("Ulysses", "Schmulysses");
    
    public static string BigStringIndex(this string s)
    {
        return String.Concat(s[0], s[1]);
    }
    
    bigStringContainer[item.BigStringIndex()].Add(item);
    

    基本上,如果您将
    string
    视为一种用于存储无限量文本的数据结构,那么您就有了不切实际的期望。对于这种大小的对象,您是否需要将它们保存在内存中(与硬盘相反)就成了问题。

    字符串的某个值。长度()大约为5MB使用字符串已经不太实际了。字符串针对短文本位进行了优化

    想想当你这样做的时候会发生什么

    msString += " more chars"
    
    比如:

    系统计算myString的长度加上“更多字符”的长度

    系统分配那个数量的内存

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

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

    最初的myString由垃圾收集器来处理

    虽然这对于小文本位来说很好,但对于大字符串来说却是一场噩梦,仅仅找到2GB的连续内存可能就是一个障碍


    因此,如果您知道要处理的字符数超过了极少数MB,请使用一个*缓冲区类。

    即使在x64版本的Windows中,我也遇到了.Net将每个对象限制为2GB的问题


    2GB对于医学图像来说非常小。2GB对于VisualStudio下载图像来说甚至很小。

    在一个集合中存储超过20亿个对象的可能性很小。在执行枚举和查找时,您将遭受一些相当严重的性能损失,这是集合的两个主要目的。如果您要处理这么大的数据集,几乎可以肯定的是,您可以采取其他一些方法,例如将单个集合拆分为许多较小的集合,这些集合包含您正在处理的整个数据集的一部分

    嘿,等一下。。。。我们已经有了这个概念——它被称为字典

    如果需要存储(例如)50亿个英语字符串,请使用以下类型:

    Dictionary<string, List<string>> bigStringContainer;
    
    然后将项目添加到bigStringContainer,如下所示:

    // Lord knows how many characters
    string ulysses = GetUlyssesText();
    
    // allocate an entirely new string of roughly equivalent size
    string schmulysses = ulysses.Replace("Ulysses", "Schmulysses");
    
    public static string BigStringIndex(this string s)
    {
        return String.Concat(s[0], s[1]);
    }
    
    bigStringContainer[item.BigStringIndex()].Add(item);
    
    今天到此为止。(显然有更有效的方法可以做到这一点,但这只是一个例子)


    哦,如果你真的需要能够通过绝对索引查找任意对象,那么使用
    数组而不是集合。好的,是的,您使用了一些类型安全性,但是如果您使用的文件是2GB,您可以使用
    long
    索引数组元素,这意味着您可能会使用大量RAM,并且您会看到非常慢的性能


    相反,对于非常大的文件,请考虑使用MyMyEclipse文件(参见:)。使用此方法,您可以处理几乎无限大小的文件,而不必将整个文件加载到内存中。

    框架使用
    Int32
    进行
    计数
    /
    长度
    属性、索引器等,这一事实有点令人费解。真正的问题是CLR当前的最大对象大小限制为2GB

    所以一个
    字符串
    ——或者任何其他单个对象——都不能大于2GB

    更改
    string
    类型的
    Length
    属性以返回
    long
    ulong
    甚至
    biginger
    都是毫无意义的,因为您的字符数无论如何都不能超过2^30个左右(最大大小为2GB,每个字符2个字节)

    类似地,由于2GB的限制,只有
    bool[]
    byte[]
    数组可以接近2^31个元素,每个元素只使用1个字节

    当然,没有什么可以阻止您创建自己的复合类型来绕过2GB限制


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

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

    如果我的答案是2GB字符串,则我