2013-04-03 35 views
2

假设我想在类中存储无限数量的元素,就像Excel使用表格数量(受计算机内存限制)一样。在.NET中存储没有限制(无限)的数字语言

哪种方法或数字类型来容纳用于获取元素的索引?

+5

['BigInteger'](http://msdn.microsoft.com/en- us/library/system.numerics.biginteger.aspx)? –

+0

在c#中,您可以使用列表或词典或任何结构,它们不具有最大大小。什么是你的需要? – Thomas

+1

@Thomas我认为'List'将会使用内部数组的最大大小,不确定'Dictionary'。 –

回答

5

如果你想存储一个任意大的整数,你可以使用BigInteger

public BigInteger Index{ get; set; } 

请注意,您必须首先添加对System.Numerics dll的引用。

它不同于.NET Framework中的其他整型,它们的范围由其MinValueMaxValue属性指示。

因为它没有上限或下限,所以可以抛出OutOfMemoryException来执行任何导致BigInteger值变得太大的操作。

1

如果你想推出自己的收藏,你可以使用Indexer。下面简单的例子可以处理100个元素,但是你可以根据需要将其扩展到尽可能多的元素,使用列表或其他一些机制:

class SampleCollection<T> 
{ 
    // Declare an array to store the data elements. 
    private T[] arr = new T[100]; 

    // Define the indexer, which will allow client code 
    // to use [] notation on the class instance itself. 
    public T this[int i] 
    { 
     get 
     { 
      // This indexer is very simple, and just returns or sets 
      // the corresponding element from the internal array. 
      return arr[i]; 
     } 
     set 
     { 
      arr[i] = value; 
     } 
    } 
} 

此类显示的客户端代码如何使用索引:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Declare an instance of the SampleCollection type. 
     SampleCollection<string> stringCollection = new SampleCollection<string>(); 

     // Use [] notation on the type. 
     stringCollection[0] = "Hello, World"; 
     System.Console.WriteLine(stringCollection[0]); 
    } 
} 
// Output: 
// Hello, World. 

使用int作为索引器参数可以让您访问大约20亿个离散元素。如果您需要更多,则必须使用long或任意精度类型,如BigInt作为索引器参数。

+1

请注意,内部数组的最大大小为'Int32.MaxValue',可能满足或不符合要求(我只能希望它,否则我可能会不由自主地提到有人做错了什么)。 –

+0

这是无用的列表存在: '列表 a =新列表(); var b = a [0];' – Thomas

+0

@AdamHouldsworth:我认为“无限”意味着“对于一些任意大的值”,因为除非你在讨论Haskell中的懒惰列表或类似的东西,否则实际上不存在无限集合之类的东西。 –

0

任何数值型变量都是有限的。我知道的最大的是ULong(0到18,446,744,073,709,551,615)。如果你的元素多于这个,你就会遇到麻烦......

0

在.Net中对于任何特定对象都有2Gb的限制。这意味着,例如,byte[]数组索引不能大于int.MaxValue - 实际上它甚至更小。

所以你可以很容易地使用Int32 == int作为任何索引,或者你应该考虑很多关于你的数据结构。

+0

.NET 4.5有一个解决64位系统的限制:http://stackoverflow.com/questions/1087982/single-objects-still-limited-to-2-gb-in-size-in-clr- 4-0 –

+0

** not ** exactly - 如果您按照链接http://msdn.microsoft.com/en-us/library/hh285054%28v=vs.110%29.aspx获取'gcAllowVeryLargeObjects'详细信息,您将请参阅此注释'对于字节数组和单字节结构数组,任何单维中的最大索引为2,147,483,591(0x7FFFFFC7),对于其他类型,则为2,146,435,071(0X7FEFFFFF)。 ' – Lanorkin

+0

够公平的,我们对这里的细节有点模糊,然后当你声明任何特定对象的2GB限制。 –

0

对于仅由可用系统内存限制的项目集合进行索引,您可能可以使用long。该范围足以唯一地寻址存储体的各个位,其大小约为驱动器空间的14PB(或大于其主存储器的207TB存储体的大小的10000倍)的TACC Stampede's的大小的150倍。

1

Tim-Schmelter和Joseph Lee为你提供了很好的答案。但考虑到它们是最大价值的好答案。不过考虑一下实现的细节:如果你的数据结构只有一个字节,那么在考虑任何其他因素(数据结构等)之前,甚至ULong的索引都可以超过exabyte的值。

0

基于添Schmelter的答案:

public class BigList<T> 
{ 
    public Object[] internalArray = new Object[Int16.MaxValue]; 

    public T this[BigInteger i] 
    { 
     get 
     { 
      if (i < Int16.MaxValue-1) 
      { 
       return (T)internalArray[(int)i]; 
      } 
      else 
      { 
       i = i - int.MaxValue; 
       BigList<T> following = (BigList<T>)internalArray[Int16.MaxValue-1]; 
       if (following != null) 
       { 
        return following[i]; 
       } 
       else 
       { 
        throw new KeyNotFoundException(); 
       } 
      } 
     } 
     set 
     { 
      if (i < Int16.MaxValue-1) 
      { 
       internalArray[(int)i] = value; 
      } 
      else 
      { 
       i = i - int.MaxValue; 
       BigList<T> following = (BigList<T>)internalArray[Int16.MaxValue-1]; 
       if (following == null) 
       { 
        following = new BigList<T>(); 
        internalArray[Int16.MaxValue - 1] = following; 
       } 
       following[i] = value; 
      } 
     } 
    } 
} 

和单元测试的开始:

[Test] 
public void BigListTest() 
{ 
    BigList<string> test = new BigList<string>(); 
    var bigIndex = new BigInteger(int.MaxValue); 
    string value = "test"; 
    bigIndex *= 2; 
    test[bigIndex] = value; 
    Assert.AreEqual(test[bigIndex],value); 
}