2009-07-04 12 views

Respuesta

20

varias razones:

  • Historia: Nullable<T> no existía hasta .NET 2.0, y no puede romper el código existente - especialmente con las diferentes reglas de boxeo para Nullable<T>
  • Significado: si quiero un int, puede ser que no quieren que sea anulable ... yo quiero que sea un int, y yo no quiero tener que el registro de entrada de la manija/nulos
  • Espacio: se añade un coste adicional a cada struct ... en particular, imag ine a byte[], y ahora considere si se pudo anular byte - mucha sobrecarga adicional; * Más que dejaría de hacer que blits etc *
  • Rendimiento: Nullable<T> añade un montón de sanciones adicionales; en particular, muchas llamadas ocultas a .HasValue y .Value/.GetValueOrDefault(); esto se muestra en particular en los "operadores levantadas" - es decir x + y se convierte en algo parecido a continuación, que se suma a los bucles apretados etc:

    (x.HasValue && y.HasValue) ? (x.GetValueOrDefault() + y.GetValueOrDefault()) : null

Del mismo modo, x == y que verificar:

  • si ambos nula => true
  • si uno null => false
  • utilizar de otro modo == en GetValueOrDefault() de cada

un montón de gastos generales ....

+0

¿No te olvidas del extra? operador que lanzaron también. int i = j ?? k; // si j es nulo, use k. –

+0

bueno, eso no es específico de 'Nullable ' - pero otro buen punto –

+0

@Chris ¿funciona eso en absoluto? j no puede ser nulo, de lo contrario no puede asignarlo a un tipo de valor, ¿verdad? ;-) –

1

tipos cuyo valor anulable son en realidad? No conozco ninguno.

EDITAR: Si se refiere al tipo de cadena, entonces no es un tipo de valor, sino un tipo de referencia.

+0

Necesita envolverlos en el tipo Nullable philsquared

+1

Pero eso es algo diferente. Creo que el tema principal significa que los tipos de valor se pueden anular de manera inmediata, probablemente haciendo referencia al tipo de cadena. – User

+1

Creo que el OP significa algo así como "si los tipos de valores se pueden convertir en nulos, ¿por qué no se pueden anular desde el principio?". – Guffa

6

Sí, hay una penalización. La estructura Nullable<T> contiene el valor y también un indicador booleano que determina la nulidad del valor.

Aunque el valor booleano es de solo un byte, las estructuras se alinean incluso con los límites de las palabras. Un int utiliza cuatro bytes de memoria, pero un int? necesita ocho bytes.

+0

La pena es mucho peor que una palabra adicional. El diseño de la estructura que admite nulos significa que la creación de un 'Nullable ' requerirá al menos una operación adicional de "copia T", y cualquier código que reciba un 'Nullable ' tendrá que realizar al menos una operación adicional de "copia T" en para usarlo – supercat

0

Además de respuesta Marc Gravell, compruebe el código reflejado desde anulable <T>:

public struct Nullable&lt;T&gt; where T: struct 
{ 
    private bool hasValue; 

    internal T value; 

    public Nullable(T value) 
    { 
     this.value = value; 
     this.hasValue = true; 
    } 

    public bool HasValue 
    { 
     get 
     { 
      return this.hasValue; 
     } 
    } 
    public T Value 
    { 
     get 
     { 
      if (!this.HasValue) 
      { 
       ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); 
      } 
      return this.value; 
     } 
    } 
    public T GetValueOrDefault() 
    { 
     return this.value; 
    } 

    public T GetValueOrDefault(T defaultValue) 
    { 
     if (!this.HasValue) 
     { 
      return defaultValue; 
     } 
     return this.value; 
    } 

    public override bool Equals(object other) 
    { 
     if (!this.HasValue) 
     { 
      return (other == null); 
     } 
     if (other == null) 
     { 
      return false; 
     } 
     return this.value.Equals(other); 
    } 

    public override int GetHashCode() 
    { 
     if (!this.HasValue) 
     { 
      return 0; 
     } 
     return this.value.GetHashCode(); 
    } 

    public override string ToString() 
    { 
     if (!this.HasValue) 
     { 
      return ""; 
     } 
     return this.value.ToString(); 
    } 

    public static implicit operator T?(T value) 
    { 
     return new T?(value); 
    } 

    public static explicit operator T(T? value) 
    { 
     return value.Value; 
    } 
} 

Usted' Notaremos la existencia del booleano HasValue y cómo las propiedades lo usan.

0

Considere la implementación.Un número entero en C# se define como

public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int> 

A struct se almacena directamente en la pila, en contraposición a los objetos referencias que son punteros a la memoria (la referencia en sí está en la pila, pero la asignación está en la pila) .

Una referencia NULL simplemente significa que el puntero en la pila no se ha inicializado a una ubicación en el montón.

Cuestiones relacionadas