2011-09-14 19 views
15

Im tratando de utilizar el siguiente código:¿Por qué no puedo declarar una lista genérica como anulable?

private Nullable<List<IpAddressRange>> ipAddressRangeToBind; 

Pero me estoy haciendo la siguiente advertencia:

La Lista de tipo debe ser un tipo de valor no anulable en fin de utilizarlo como una parámetro 'T' en el tipo genérico o método 'System.Nullable'.

Respuesta

35

List<T> ya es un tipo de referencia (para cualquier tipo de T) - Sólo se pueden declarar Nullable<T> donde T es un tipo de valor no anulable (se declara como Nullable<T> where T : struct).

Pero eso está bien, porque si sólo declara:

private List<IpAddressRange> ipAddressRangeToBind; 

entonces usted todavía puede tener

ipAddressRangeToBind = null; 

porque los tipos de referencia son siempre anulable.

+0

¡qué respuesta!, Gracias ..... fácil de explicar – Ajay2707

9

List<IpAddressRange> es un tipo de referencia - ya puede contener nulos - de hecho se inicializará a nulo por esa declaración.

5

sólo puede utilizar tal cual:

List<IpAddressRange> ipAddressRangeToBind = null; 

lista ya es anulable.

+0

cierto, ¿por qué no puedo hacerlo sin interés ...? – Exitos

+2

Supongo que porque, como explicó The Jon Skeet, el de la restricción 'Nullable donde T: struct' y' IpAddressRange' no es una 'struct'. ¿Por qué la restricción que preguntas?Esa es una pregunta diferente :) –

+0

@ Pete2k: Agregué una respuesta sobre por qué no existe la restricción. No fue la primera respuesta, así que no quiero reclamar el crédito por la respuesta, pero fue demasiado tiempo para poner un comentario ... –

4

Los tipos de referencia no pueden incluirse en Nullable<T> debido a una restricción where T : struct en el genérico.

Las razones de esta restricción son:

  1. tipos de referencia son ya anulable por definición, y
  2. anulable no es muy eficiente del espacio, sino más bien una nulabilidad "lógica".

Nullable<T> tiene una propiedad bool HasValue y un tipo T propiedad Value que contiene el valor de tipo de valor real.

Incluso si HasValue == false (es decir, si la variable envolvente con nulos está establecida en null), TODAVÍA consume el espacio para el tipo de valor como si estuviese allí.

Es lógicamente anulable que le permite especificar el comportamiento opcional, pero no guarda ningún espacio. Esto es muy similar a cómo boost :: optional funciona en C++.

+0

¡Ahora veo qué es la cláusula Where! – Exitos

+0

Muchas de las molestias con 'Nullable ' provienen del deseo de que pretenda que una instancia vacía es' null'. Una decisión desafortunada, en mi humilde opinión, ya que impide métodos como 'TryGetValue', que pueden o no tener una' T' para devolver, simplemente devolver un 'TValue'' sin tener que preocuparse por el tipo de' TValue' (si el 'HasValue' del elemento devuelto es falso, la clave no existe; si' HasValue' es verdadero, la clave existe incluso si el 'Valor 'almacenado es' nulo'). Por otro lado, mientras que los tipos que aceptan nulos deben ser lógicamente covariantes con su parámetro de tipo ... – supercat

+0

... (dado que cualquier 'Animal?' Debería ser capaz de contener el contenido de cualquier 'Cat?'), Haciendo que la covarianza funcione teniendo un lanzamiento de 'Animal?' o 'Animal ??' a 'Object' preservar el grado de nulability, requeriría que la conversión de un tipo que admite nulo a' Object' no use el boxeo normal. En las reglas de boxeo normales, los tipos de valores encuadrados son * siempre * mutables (incluso si el tipo de valor subyacente es supuestamente "inmutable"). Es una lástima, ya que dicho diseño aumenta la dificultad de hacer que las cosas como una interfaz de "diccionario legible" sean covariantes con respecto a los tipos de valores almacenados en ellas. – supercat

Cuestiones relacionadas