2008-08-08 10 views
77

? ¿Por qué Array.Length es un int, y no un uint. Esto me molesta (solo un poco), porque un valor de longitud nunca puede ser negativo.¿Por qué Array.Length es un int, y no es un error

Esto también me obligó a utilizar un int para una longitud de la propiedad en mi propia clase, porque cuando se especifica un valor int, esto debe convertir explícitamente ...

Así que la pregunta final es : ¿hay algún uso para un int sin firmar (uint)? Incluso Microsoft parece no usarlos.

+0

A pesar de los problemas que aparecen a continuación, creo que debería cambiar a UInt. – alan2here

+1

@ alan2here hacer ese cambio rompería casi todos los códigos, ¡así que no sucederá si me preguntan! – Peter

Respuesta

0

Normalmente, los valores enteros están firmados, a menos que necesite explícitamente un valor sin signo. Es solo la forma en que se usan. Puede que no esté de acuerdo con esa elección, pero así son las cosas.

Por el momento, con las restricciones de memoria típicas de hoy, si su matriz o estructura de datos similar necesita una longitud UInt32, debe considerar otras estructuras de datos.

Con una matriz de bytes, Int32 le dará 2 GB de valores

+13

"pero así son las cosas". - No, las cosas nunca son solo como son. Siempre se toma una decisión de diseño, y siempre vale la pena preguntar por qué. Uno podría aprender algo de los pros y los contras, o involucrar al diseñador (en algunos casos) en una discusión sobre ellos. ¡Siempre haz preguntas! :) –

1

Creo que también podría tener que ver con la simplificación de cosas en un nivel inferior, ya que Array.Length por supuesto se agregará a un número negativo en algún momento, si Array.Length no se firmaron, y se agregó a un int negativo (dos complemento), podría haber resultados desordenados.

+0

Por favor, dé un ejemplo? 'uint lenght = 3; int x = -4; Console.WriteLine (x + longitud);' produce -1 bien. –

1

Parece que nadie brindó respuesta a "la última pregunta".

Creo que el uso principal de ints sin firmar es facilitar la interfaz con sistemas externos (P/Invoke y similares) y cubrir las necesidades de varios idiomas que se transfieren a .NET.

+0

Los tipos sin signo son esenciales al concatenar múltiples valores más pequeños para producir uno más grande. Uno puede combinar dos UInt16 para hacer un UInt32 computando '(HighPart << 16) + LowPart', y uno puede dividir un UInt32 en dos UInt16 a través de' (Uint16) (Value >> 16) 'y' (Uint16) (Value & 65535) '. Tales operaciones serían muy inconvenientes si 'LowPart' tuviera que ser un tipo firmado. Habiendo dicho eso, las interacciones entre tipos firmados y no firmados a menudo son confusas y problemáticas. Los tipos sin firmar deberían considerarse en muchos sentidos como un mundo propio. – supercat

45

Muchas razones:

  • uint no es compatible con CLS, haciendo así construido en un tipo (array) que dependen de ella habrían sido problemático
  • El tiempo de ejecución como originalmente diseñado prohíbe cualquier objeto en el montón que ocupa más de 2GB de memoria. Como la matriz de tamaño máximo que sería inferior o igual a este límite sería un byte nuevo [int.MaxValue], sería desconcertante para las personas poder generar longitudes de matriz positivas pero ilegales.
  • Históricamente C# hereda gran parte de su sintaxis y convención de C y C++.En esas matrices, simplemente se trata de una aritmética de punteros, por lo que era posible indexar matrices negativas (aunque normalmente son ilegales y peligrosas). Dado que gran parte del código asume que el índice de matriz está firmado, esto habría sido un factor
  • En una nota relacionada, el uso de enteros con signo para índices de matriz en C/C++ significa que la interoperabilidad con estos idiomas y funciones no administradas requeriría el uso de en cualquier caso, lo que puede confundir debido a la inconsistencia.
  • La implementación de BinarySearch (un componente muy útil de muchos algoritmos) se basa en poder usar el rango negativo de int para indicar que no se encontró el valor y la ubicación en la que se debe insertar dicho valor para mantener clasificación.
  • Al operar en una matriz, es probable que desee tomar una compensación negativa de un índice existente. Si utilizó un desplazamiento que lo llevaría más allá del inicio de la matriz con la unidad, entonces el comportamiento de ajuste haría que su índice fuera legal (en el sentido de que es positivo). Con un int el resultado sería ilegal (pero seguro ya que el tiempo de ejecución evitaría leer la memoria no válida)
+2

Si nada en el montón puede ser superior a 2 Gb, entonces casi todas las matrices de longitud int.MaxValue son ilegales ya que la mayoría de los tipos son más grandes que 1 byte. – ScottS

+0

de hecho, pero ((uint) (int.MaxValue)) + 1 estaría garantizado incorrecto para * cualquier cosa *. int en sí no es perfecto, pero el equilibrio de las cosas hace que sea legítimo quedarse con int como tipo. – ShuggyCoUk

+0

Comenzar con ser un tipo explicto ArrayIndex (esencialmente size_t) que se traduciría de forma limpia y segura a un int según sea necesario, quizás haría más fácil en el futuro hacer realmente uso permitiendo matrices de> 2GB en el futuro con menos dolor. Pero la pragmática dice que Java tiene el mismo problema, ¿por qué tomar el riesgo? – ShuggyCoUk

Cuestiones relacionadas