2012-06-08 11 views
13

que quería probar a asignar una matriz de bytes 4 mil millones y este es mi código C#:¿Por qué se permite "largo" como longitud de matriz en C#?

long size = 4 * 1000; 
size *= 1000; 
size *= 1000; 
byte[] array = new byte[size]; 

este código falla con System.OverflowException en la línea que contiene new. De acuerdo, resulta Length devuelve int, por lo que la longitud de la matriz también se limita a lo que int puede almacenar.

Entonces, ¿por qué no hay error de tiempo de compilación y long se puede utilizar como el número de elementos de la matriz en la asignación?

+4

'Array.CreateInstance()' da el mensaje de error más significativo, "no se admiten matrices más grandes de 2 GB." –

+0

Así que está asignando 3.7 GB de memoria. ¿Cuánta RAM está instalada en su máquina? : D – konqi

+0

JoSo, la cantidad de memoria física no tiene importancia allí. – Joey

Respuesta

15

Debido a que la especificación dice en la sección 7.6.10.4:

Cada expresión de la lista expresión debe ser de tipo int, uint, long o ulong, o convertir implícitamente a uno o más de estos tipos .

Esto es más probable que fácilmente permitir creación de matrices mayores a 2 GB, a pesar de que no son compatibles todavía (pero no podrá contar con un lenguaje cambio una vez que el CLR hace que un cambio de este tipo) . Mono does support this, however y .NET 4.5 apparently will allow larger arrays too.

En cuanto a la longitud de la matriz es un int por cierto: También existe LongLength, que devuelve long. Esto estaba en .NET 1.1 y probablemente un cambio a prueba de futuro.

+1

+1 Buen lugar en las cosas de 4.5, espero por Dios, nunca veo eso activado en nuestra aplicación ... –

+1

Parece que incluso con el cambio de 4.5, el código en cuestión todavía fallará porque dice "El índice máximo en cualquier la dimensión única es 2.147.483.591 (0x7FFFFFC7) para matrices de bytes y matrices de estructuras de un solo byte, y 2.146.435.071 (0X7FEFFFFF) para otros tipos. " –

+0

De hecho. Podría hacerlo una matriz multidimensional para evitar eso, entonces. Pero eso es desagradable también. – Joey

6

Es una limitación de la CLR, ningún objeto solo puede exceder de 2 GB, incluyendo arrays:

Large array C# OutOfMemoryException

Esto es independientemente de 32 bits o de 64 bits OSs. Dicho eso, no evita que uses más de esa cantidad en total, solo que no en un objeto.

Es un errortiempo de ejecución porque si se mantiene la long (u otro valor de inicialización) dentro del rango, que va a funcionar.

Puede inicializar matrices con todos los tipos integrales: sbyte, char, short, int, y long - todo de compilación; las variantes sin firmar también funcionan.

3

El long es un tipo integral, por lo que se puede usar para definir la matriz; la excepción es construir demasiado grande de una matriz, no específicamente al usar un long.

Ex, esto funciona muy bien:

long size = 20; 
byte[] array = new byte[size]; 
9

qué tiempo se permitirá la longitud de la matriz?

respuesta es: mucho tiempo en .net significa Int64

Y indexación de matrices se puede Int64 acuerdo con la especificación.

2da pregunta: ¿Por qué se muestra overflowexception?

Como no se puede asignar ningún objeto a más de 2 GB de memoria.

+2

Con tales notificaciones (a menos que sean obvias, por ejemplo 'long' es un alias para' System.Int64') siempre es bueno hacer una copia de seguridad de las mismas con referencias. – Joey

+1

No estoy de acuerdo con su segundo punto. Si está fuera de memoria, debería esperar una OutOfMemoryException, no una OverflowException. De acuerdo con la especificación, una excepción OverflowException solo debe plantearse si la longitud es menor que cero. – Mishax

+1

@Mishax: No se ha agotado la memoria, es solo que un solo objeto no puede ser más grande que eso. – Joey

Cuestiones relacionadas