2011-10-10 14 views
5

Ha habido muchas preguntas sobre el soporte para tipos de referencia que no admiten nulos en .NET. La gran esperanza eran los contratos de código, pero se limita a la verificación en tiempo de ejecución para aquellos que tienen un presupuesto limitado.Tipos de referencia que no admiten nulos (una vez más)

En cuanto a los enfoques que no sean contratos de código, Jon Skeet escribió un blog post sobre esto hace unos años, y uno de los comentaristas proporcionó un aspecto útil NonNull struct que tenía IL modificado para deshabilitar el constructor predeterminado. Esto parece un enfoque excelente, y me puedo imaginar extenderlo para proporcionar todo tipo de microtypes que no admite nulos. La manipulación de IL podría ser un paso posterior a la creación desencadenado por un atributo en la estructura, p.

//Microtype representing a non-zero age, so we want to disable the default ctor 
[NoDefaultConstructor] 
public struct Age 
{ 
    public Age(int age) 
    { 
     // Implementation (including validation) elided 
    } 
} 

Antes de seguir investigando, me gustaría preguntar si alguien sabe de algún problema que esto pueda causar. No he podido pensar en ninguno.

+0

¿Cuál es su caso de uso para necesitar un tipo de referencia no nulo? –

+1

Para aquellos cuyo presupuesto se extiende a ReSharper, hay alguna funcionalidad útil para verificar la nulidad allí (aunque obviamente no tan completa como los contratos en las costosas ediciones de VS) – AakashM

+0

@AnthonyPegram Creo que la mayoría de los usos de los tipos de referencia son implícitamente no nulos , por lo que exigir que a través de la firma del método sea un triunfo en términos de documentación y seguridad. – Akash

Respuesta

6

Esto se puede vencer con bastante facilidad: el tiempo de ejecución no intenta llamar al constructor sin parámetros de una estructura (si está presente) en cada escenario.

En particular, no se llamará al crear una matriz del tipo struct.

Age[] ages = new Age[3]; 

// This guy skips your "real" ctor as well as the "invalid" parameterless one. 
Age age = ages[0]; 

... o en default(structType) expresiones:

// Invalid state here too. 
Age age = default(Age); 

De Jon Skeet de empirical research en estas cosas, he aquí una lista de otras operaciones que no llama al constructor:

  • Acaba de declarar una variable, ya sea local, estática o instancia
  • Boxeo
  • Usando default(T) en un método genérico
  • Usando new T() en un método genérico

Ahora la situación que le deja en es que usted tiene que probar alguna manera para cada Age ejemplo, si la instancia o no fue creado al trabajar alrededor de su cerca, lo cual no es mucho mejor que no haber levantado la cerca en primer lugar.

+0

Gracias Ani, echaba de menos el artículo de seguimiento de Jon. Si bien todas estas son preocupaciones válidas, todavía me pregunto si el enfoque tiene mérito, especialmente para el código interno, p. NonNull en una firma de método es una documentación clara (con * algún * cumplimiento del compilador) en cuanto a los valores permitidos para el argumento. Me siento cómodo con una solución imperfecta si las imperfecciones solo están expuestas a través de usuarios maliciosos (mis colegas son profesionales) o por accidentes poco comunes. Sin embargo, no he decidido si sus ejemplos caen en la categoría de "accidente raro". – Akash

+0

@Akash: Difícilmente clasificaría una matriz de estructuras o 'por defecto (T)' en un método genérico que probablemente sea "malicioso"/un "accidente raro". Una vez que lo aceptemos, está claro que vamos a tener que validar cada instancia, lo que nos permite volver a empezar. :) – Ani

+0

Pero si estamos limitando la discusión a microtipos, no puedo ver por qué alguien podría crear una instancia a través de un método de fábrica genérico (GetMicroType ). Del mismo modo, en lugar de pasar Age [] en un método, pasaría una AgeCollection, que a su vez tendría validación en sus argumentos. Estoy luchando por ver lo que me estoy perdiendo, pero dado que no conozco a nadie que use este enfoque, creo que debe haber problemas prácticos más que teorías. – Akash

Cuestiones relacionadas