2012-06-08 10 views
6

en cuenta lo siguiente:Asignación de matrices grandes; OutOfMemoryException VS OverflowException

long size = int.MaxValue; 
long[] huge = new long[size];  // throws OutOfMemoryException 
long[] huge = new long[size + 1]; // throws OverflowException 

Sé que hay un límite de 2 GB en el tamaño de un objeto único, lo que explica la primera excepción, pero ¿Por qué aparece una excepción diferente una vez que el número de elementos supera los 32 bits?

(Estoy usando una computadora de 64 bits si eso es importante).

EDIT: I también pueden definir y usar un indexador que acepta un long sin problemas:

internal sealed class MyClass 
{ 
    public object this[long x] 
    { 
     get 
     { 
     Console.WriteLine("{0}", x); 
     return null; 
     } 
    } 
} 

... 

long size = int.MaxValue; 
MyClass asdf = new MyClass(); 
object o = asdf[size * 50]; // outputs 107374182350 
+0

Use en su lugar una 'Lista ' genérica que utiliza solo tanta memoria como sea necesario. –

Respuesta

2

Así que de lo que he reunido, algo así como lo siguiente está sucediendo aquí:

  • indexadores en general podría utilizar cualquier tipo de parámetro.
  • El built-in indexadores matriz puede aceptar cualquier tipo integral ...
  • Pero la implementación subyacente de los indexadores de matriz incorporados requiere un valor que es <= Int32.MaxValue y lanzará una excepción de desbordamiento por un valor que supera Int32.MaxValue.

Si bien este último punto se siente como una especie de contradicción extraña (aceptando tipos más grande que Int32, pero lanzar una excepción si quieres pasar a utilizar realmente cualquiera de esos bits extra), que es al parecer un efecto secundario de la hecho de que parte de esto está implementado a medias para la implementación futura de matrices que tendrán más de Int32.MaxValue elementos.

8

arrays de C# son indexados por System.Int32. Como size + 1 está más allá de Int32.MaxValue, obtiene un desbordamiento de enteros.

Utilice la sobrecarga de Array.CreateInstance que en su lugar tarda un tiempo, si realmente desea utilizar un long como índice.

+0

entonces, ¿se nos permite usar una variable 'long' como un índice o especificador de tamaño, pero solo si el valor no es mayor que 32 bits? eso parece extraño; ¿No debería el compilador requerir un 'Int32'? ¿Por qué usar 'long's como índices si 32 bits es el límite del índice? –

+1

A través de la subscripción de matrices (indexadores: '[índice]') solo puede usar 'int'. Si desea usar un 'long', debe usar los métodos' GetValue' y 'SetValue'. –

+3

Vale la pena señalar que 'Array.CreateInstance' no resuelve el problema. Aún no puede crear una matriz demasiado grande. Se hace una pregunta relacionada [aquí] (http://stackoverflow.com/questions/10945404/why-is-long-being-allowed-as-array-length-in-c/10945507#10945507), a partir de .NET 4.5, las matrices más grandes son compatibles con los sistemas de 64 bits. Todos los tipos integrales se pueden usar como inicializadores de matriz en tiempo de compilación. –

Cuestiones relacionadas