Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 你能使用列表吗<;列表<;结构>&燃气轮机;要绕过2gb的对象限制?_C#_Memory_Memory Management_Reference_64 Bit - Fatal编程技术网

C# 你能使用列表吗<;列表<;结构>&燃气轮机;要绕过2gb的对象限制?

C# 你能使用列表吗<;列表<;结构>&燃气轮机;要绕过2gb的对象限制?,c#,memory,memory-management,reference,64-bit,C#,Memory,Memory Management,Reference,64 Bit,我在c#中遇到了2gb的对象限制(由于一些恼人的原因,这甚至适用于64位)和大量的结构集合(估计大小总共为4.2 gig) 现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗 我的理由是,只有CLR中的硬编码限制才能阻止我在64位平台上实例化9gig对象,这与系统资源完全无关。列表和数组也是引用类型,因此包含列表的列表实际上只包含对每个列表的引用。因此,没有任何对象超过大小限制 这有什么原因不起作用吗?我现在想自

我在c#中遇到了2gb的对象限制(由于一些恼人的原因,这甚至适用于64位)和大量的结构集合(估计大小总共为4.2 gig)

现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗

我的理由是,只有CLR中的硬编码限制才能阻止我在64位平台上实例化9gig对象,这与系统资源完全无关。列表和数组也是引用类型,因此包含列表的列表实际上只包含对每个列表的引用。因此,没有任何对象超过大小限制

这有什么原因不起作用吗?我现在想自己试试,但我手头没有内存分析器来验证

现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗

是的-但是,如果你想在这个限制范围内工作,我会考虑使用数组,而不是让<代码>列表< /Cord>类管理数组。

CLR中的2gb单对象限制正是单对象实例。当你制作一个结构的数组(它是
List
内部使用的)时,整个数组就是CLR中的“一个对象实例”。但是,通过使用
列表
或锯齿状数组,每个内部列表/数组都是一个单独的对象,这允许您有效地拥有任意大小的对象

CLR团队实际上在博客上对此进行了讨论,并提供了一个类似于单个
列表的实现,但在内部为您执行“阻塞”管理。这是获取>2gb列表的另一个选项


请注意,.NET 4.5将提供选项,但您必须明确选择使用。

这里有一篇关于此主题的有趣文章:


关于编写自己的“BigArray”对象。

列表
包含4或8字节的引用,具体取决于您是在32位还是64位模式下运行,因此,如果引用的2GB对象不会将实际<代码>列表大小增加到2GB,但只会增加字节数,则有必要引用该对象

这将允许您引用数百万个对象,每个对象可能为2GB。如果
列表
中有4个对象,每个对象都是2GB,那么
列表
将引用8GB的对象,但
列表
对象只会额外使用4*8=32字节

列表
达到2GB限制之前,在32位机器上可以保存的引用数为5.3687亿,在64位机器上为2.6843亿

5.36亿个引用*2 GB=大量数据


p.S.Reed指出,上述情况适用于引用类型,但不适用于值类型。因此,如果您持有值类型,那么您的解决方案是有效的。有关详细信息,请参阅下面的注释。

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

类HugeList
class HugeList<T>
{
    private const int PAGE_SIZE = 102400;
    private const int ALLOC_STEP = 1024;

    private T[][] _rowIndexes;

    private int _currentPage = -1;
    private int _nextItemIndex = PAGE_SIZE;

    private int _pageCount = 0;
    private int _itemCount = 0;

    #region Internals

    private void AddPage()
    {
        if (++_currentPage == _pageCount)
            ExtendPages();

        _rowIndexes[_currentPage] = new T[PAGE_SIZE];
        _nextItemIndex = 0;
    }

    private void ExtendPages()
    {
        if (_rowIndexes == null)
        {
            _rowIndexes = new T[ALLOC_STEP][];
        }
        else
        {
            T[][] rowIndexes = new T[_rowIndexes.Length + ALLOC_STEP][];

            Array.Copy(_rowIndexes, rowIndexes, _rowIndexes.Length);

            _rowIndexes = rowIndexes;
        }

        _pageCount = _rowIndexes.Length;
    }

    #endregion Internals

    #region Public

    public int Count
    {
        get { return _itemCount; }
    }

    public void Add(T item)
    {
        if (_nextItemIndex == PAGE_SIZE)
            AddPage();

        _itemCount++;
        _rowIndexes[_currentPage][_nextItemIndex++] = item;
    }

    public T this[int index]
    {
        get { return _rowIndexes[index / PAGE_SIZE][index % PAGE_SIZE]; }
        set { _rowIndexes[index / PAGE_SIZE][index % PAGE_SIZE] = value; }
    }

    #endregion Public
}
{ 私有常量int PAGE_SIZE=102400; 私有const int ALLOC_STEP=1024; 私有T[][]索引; 私有int_currentPage=-1; 私有int_nextItemIndex=页面大小; 私有int_pageCount=0; 私有整数_itemCount=0; #区域内部 私有void AddPage() { 如果(++\u currentPage==\u pageCount) 扩展页面(); _rowIndexes[_currentPage]=新的T[页面大小]; _nextItemIndex=0; } 私有无效扩展页() { 如果(_rowIndexes==null) { _rowIndexes=new T[ALLOC_STEP][]; } 其他的 { T[][]行索引=新的T[_行索引.Length+ALLOC_步长][]; Copy(_rowIndexes,rowIndexes,_rowIndexes.Length); _行索引=行索引; } _pageCount=_rowIndexes.Length; } #端部内部构件 #地区公众 公共整数计数 { 获取{return\u itemCount;} } 公共作废新增(T项) { 如果(_nextItemIndex==页面大小) AddPage(); _itemCount++; _行索引[\u currentPage][\u nextItemIndex++]=项; } 公共T此[int索引] { 获取{return{rowIndexes[index/PAGE_SIZE][index%PAGE_SIZE];} 设置{rowIndexes[索引/页面大小][索引%页面大小]=value;} } #终端区公共 }
一个有趣的C#问题有4分钟没有得到回答。我感觉到Jon Skeet正在接近……出于好奇,它需要是一个
列表
还是
列表
?你可以使用
LinkedList
@JamesMichaelHare你可以,但是你会有大量额外的开销,因为每个
LinkedListNode
都是一个独立的类,有多个引用。Related@digEmAll如果你的结构足够大,那么它根本不应该是一个结构。。。设计指南说,任何大于16字节的对象都应该是一个类:
LinkedListNode
单独有3个引用,而在x64上,仅24字节。。。LinkedList与List的性能语义也完全不同。
List与值类型一起使用时,不包含引用(对内部数组的引用除外),但数组本身直接是值类型的数组(
T[]
)。一个包含1000个元素的
列表,其中MyStruct是1000字节,将使用1000000字节。Th