¿Puede un tipo de referencia no anulable en C # 8 ser nulo en tiempo de ejecución?

10

Me parece que realmente no hay garantía de que una variable no anulable nunca tenga nulo. Imagine que tengo una clase que tiene una propiedad que no es anulable:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

Ahora eso puede parecer que ahora no puede ser nulo. Pero si hacemos referencia a esta clase con otra biblioteca que no utiliza contexto anulable, nada impide que envíe nulo allí.

¿Es correcto o hay algunas comprobaciones de tiempo de ejecución que quizás lo aseguren?

Ilya Chernomordik
fuente
Es public void Foo(string test){...}o public Foo(string test){...}?
huMpty duMpty
Gracias, lo he arreglado. Eso es lo que sucede cuando el hombre depende demasiado de R # para generar constructores :)
Ilya Chernomordik
2
C # 9 (probablemente) agregará validación nula simplificada .
Steven
En resumen, la función de "tipos de referencia anulables" está completamente rota.
Alejandro

Respuestas:

9

Esto es lo que dice MS sobre ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

El compilador no puede validar todas las llamadas a sus API públicas, incluso si su código se compila con contextos de anulación anulables habilitados. Además, sus bibliotecas pueden ser consumidas por proyectos que aún no han optado por utilizar tipos de referencia anulables. Valide las entradas a las API públicas aunque las haya declarado como tipos no anulables.

Dmitri Tsoy
fuente
2

alguien siempre puede hacer

var myFoo = new Foo(null);

Puede ser que pueda usar el diseño impulsado por dominio

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}
Humpty Dumpty
fuente
Sí, tienes razón, es solo una advertencia de todos modos, supongo. Espero que en el futuro realmente puedan hacerla cumplir de alguna manera como, por ejemplo, en Kotlin
Ilya Chernomordik
2

Estás en lo correcto, otro código que no está usando la nueva característica podría asignar nulo a esta propiedad, no hay verificaciones en tiempo de ejecución, solo son sugerencias de cumplimiento.

Siempre puede hacerlo usted mismo si desea una verificación de tiempo de ejecución:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

Tenga en cuenta que puede garantizar que no sea nulo en la mayoría de su código, solo necesita agregar guardias a su API pública de nivel superior y asegurarse de que las clases estén debidamente selladas, etc.

Por supuesto, la gente todavía puede usar la reflexión para joder su código, pero luego depende de ellos

Milney
fuente
Entonces, esto efectivamente significa que todavía puedo obtener una excepción de referencia nula a pesar de que uso el tipo no anulable, ¿verdad?
Ilya Chernomordik
Bueno ... no puede en el código que compila, porque tiene las pistas ... pero el código de otras personas que no tienen las pistas, pero hace referencia a su código, sí, pueden obtener una excepción nula
Milney
Bueno, si, por ejemplo, un fabricante de automóviles usa su constructor, o algo así, sigue siendo usted quien tendrá la excepción :)
Ilya Chernomordik
Of course people can still use reflection to f*** your code up, cierto, cierto de hecho. Definitivamente puedes usar la reflexión para hacer esto, se recomienda , no , la gente todavía lo hace, sí.
Çöđěxěŕ
2

Incluso en su propio código, si elige hacerlo, puede pasar null, utilizando el operador que perdona los valores nulos. null!se considera no nulo en lo que respecta al análisis de nulabilidad del compilador.

Damien_The_Unbeliever
fuente
-1

Para tratar con verificaciones nulas y también hacer que su código sea legible, sugiero el patrón de diseño de objetos nulos.

Más lectura aquí:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

Básicamente, implica crear un nuevo objeto que se deriva de la misma interfaz y tiene una instancia nula.

Ejemplo:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

No se pueden evitar los valores nulos, sin embargo, se pueden verificar limpiamente.

Gauravsa
fuente