2

Suppose I want to store a unlimited number of elements in a class, as Excel do with the number of Sheets (limited by the memory of the computer).

Which is the way or the number type to hold the index used to get the elements?

SysDragon
  • 9,692
  • 15
  • 60
  • 89

7 Answers7

6

If you want to store an arbitrarily large integer you can use BigInteger.

public BigInteger Index{ get; set; }

Note that you have to add a reference to the System.Numerics dll first.

It differs from other integral types in the .NET Framework which have a range indicated by their MinValue and MaxValue properties.

Because it has no upper or lower bounds an OutOfMemoryException can be thrown for any operation that causes a BigInteger value to grow too large.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

If you want to roll your own collection, you can use an Indexer. The following trivial example can handle 100 elements, but you can extend it to as many elements as you need, using a List or some other mechanism:

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;
        }
    }
}

This class shows how client code uses the indexer:

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.

Using an int as the indexer parameter will give you access to roughly two billion discrete elements. If you need more than that, you'll have to use long or an arbitrary-precision type like BigInt as the indexer parameter.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • 1
    Note that the internal array will have a maximum size of `Int32.MaxValue`, which may or may not meet the requirements (I can only hope it does, otherwise I'm liable to involuntarily mention that someone is doing something wrong). – Adam Houldsworth Apr 03 '13 at 14:53
  • That's useless as List exist : 'List a = new List(); var b =a[0];' – Thomas Apr 03 '13 at 14:54
  • @AdamHouldsworth: I assume that "unlimited" means "for some arbitrarily large value," since there really is no such thing as an infinite collection unless you're talking about lazy lists in Haskell or something like that. – Robert Harvey Apr 03 '13 at 14:55
  • @Thomas: I don't know what you mean. It's just an example; you can return anything you want to from an indexer. Read the linked article. – Robert Harvey Apr 03 '13 at 14:55
  • @RobertHarvey There is nothing in the framework, but I suppose it should be possible in theory to create one. I was just mentioning the size limit for completeness. I would actually hope an array never reaches that size really. – Adam Houldsworth Apr 03 '13 at 14:56
  • @ Robert Harvey♦ What is the advantage over a simple List? This is my question. And here your number max of element is 100, not infinite! – Thomas Apr 03 '13 at 14:58
  • 2
    @Thomas That number is just an example. And it doesn't add anything over `List` but importantly does demonstrate how indexers work in C#. An implementation that didn't use an array internally would add value over `List` by removing the array maximum size limitation. This would have to be entirely custom and likely the indexer would have to be either `long` or `BigInteger` if `long` wasn't big enough. – Adam Houldsworth Apr 03 '13 at 14:58
  • @ Robert Harvey♦ Thank you for your example, I used it as a base for an answer. – Thomas Apr 03 '13 at 15:33
1

Tim-Schmelter and Joseph Lee have good answers for you. But consider that they're good answers for maximum value. Think about the details of implementation, though: If your data structure is just one byte, even a ULong could index more than an exabyte's worth of before considering any other factors (data structures, etc).

Reacher Gilt
  • 1,813
  • 12
  • 26
0

Any numeric-type variable is finite. The largest that I know of is ULong (0 through 18,446,744,073,709,551,615). If you have more elements than this, you're in trouble...

jlee88my
  • 2,935
  • 21
  • 28
0

In .Net there is a 2Gb limit for any particular object. This means that, for example, byte[] array index can not be larger than int.MaxValue - and actually it is even smaller.

So you can easily use Int32 == int for any index, OR you should think a lot about your data structures.

Lanorkin
  • 7,310
  • 2
  • 42
  • 60
  • .NET 4.5 has a solution to that limit for 64-bit systems: http://stackoverflow.com/questions/1087982/single-objects-still-limited-to-2-gb-in-size-in-clr-4-0 – Adam Houldsworth Apr 03 '13 at 14:57
  • **not** exactly - if you follow the link http://msdn.microsoft.com/en-us/library/hh285054%28v=vs.110%29.aspx for `gcAllowVeryLargeObjects` details you will see this remark `The maximum index in any single dimension is 2,147,483,591 (0x7FFFFFC7) for byte arrays and arrays of single-byte structures, and 2,146,435,071 (0X7FEFFFFF) for other types. ` – Lanorkin Apr 03 '13 at 14:59
  • Fair enough, we are both a little vague on the details here then as you state a 2GB limit for any particular object. – Adam Houldsworth Apr 03 '13 at 15:02
0

For indexing a collection of items limited only by the available system memory, you can probably use a long. The range is enough to uniquely address the individual bits of a storage bank nearly 150x the size of TACC Stampede's 14PB of drive space (or more than 10000x the size of its 207TB bank of main memory).

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
0

Based on the answer of Tim 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;
            }
        }
    }
}

And a start of unit test :

[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);
}
Thomas
  • 5,603
  • 5
  • 32
  • 48