Tipo de referencia anulable en C # 8 cuando se utilizan clases DTO con un ORM

9

Activé esta función en un proyecto que tiene clases de objetos de transferencia de datos (DTO), como se indica a continuación:

public class Connection
    {
        public string ServiceUrl { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        //... others 
    }

Pero me sale el error:

CS8618: La propiedad no anulable 'ServiceUrl' no está inicializada. Considere declarar la propiedad como anulable.

Esta es una clase DTO, por lo que no estoy inicializando las propiedades. Esto será responsabilidad del código que inicializa la clase para garantizar que las propiedades no sean nulas.

Por ejemplo, la persona que llama puede hacer:

var connection = new Connection
{
  ServiceUrl=some_value,
  //...
}

Mi pregunta: ¿Cómo manejar tales errores en las clases DTO cuando el contexto de nulabilidad de C # 8 está habilitado?

M.Hassan
fuente
3
Cuando realiza la inicialización de la construcción de la manera que muestra, se ejecuta el constructor predeterminado (inicializando ServiceUrl a su valor predeterminado (que, para las cadenas, es nulo)). Luego, se ejecuta la instrucción initialize. Si desea que no sea anulable, debe salir de todos los constructores inicializados
Flydog57
POCO no significa que no tiene constructor o que las propiedades no están inicializadas. Significa Plain Old C# Object. Solo un objeto como cualquier otro, sin heredar de ninguna clase especial. Sospecho que tienes una pregunta diferente . Cómo crear DTOs -Data Transfer Objects
Panagiotis Kanavos
This should be the responsibility of the one initializing the class to ensure that the properties are non-nullla clase debe estar en un estado válido siempre. Si nullno está permitido, la propiedad nunca debe ser nula. Tal vez, en lugar de una cadena básica, debería usar una clase especializada para la URL que pueda tener un valor de None'Falta', como la clase Opción en F #. C # 8 le permite escribir tales clases y verificarlas con coincidencia de patrones
Panagiotis Kanavos
@Panagiotis Kanavos, la clase, en mi caso, tiene una restricción para ser un constructor sin parámetros. Así que tengo que utilizar la propiedad inicializador: public string ServiceUrl { get; set; } = default! ;. Espero que Roslyn pueda tener en el futuro una forma de manejar la inicialización tardía fuera del alcance de ctor. Estaba usando MayBe <T> (como la clase Opción), pero cambié a Tipo de referencia anulable en c # 8 para el nuevo código.
M.Hassan
Los NRT no son Maybes, de hecho, los Maybes ahora son aún más importantes y más fáciles de usar. Siempre que, por supuesto, estén construidos con expresiones idiomáticas de C # que los hacen fáciles de trabajar con la coincidencia de patrones
Panagiotis Kanavos

Respuestas:

9

La siguiente solución es recomendada por EF Core y EF6 ver

1) Inicializando a null!con el operador indulgente

public string ServiceUrl { get; set; } = null! ;
//or
public string ServiceUrl { get; set; } = default! ;

2) Uso del campo de respaldo:

        private string _ServiceUrl;
        public string ServiceUrl
        {
            set => _ServiceUrl = value;
            get => _ServiceUrl
                   ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ServiceUrl));
        }

M.Hassan
fuente
La pregunta mencionó que no puede usar el !operador.
Athanasios Kataras
No puedo usar! con tipo, pero el enlace que mencioné muestra cómo inicializar usando null !. Es una solución alternativa. Modifiqué la pregunta.
M.Hassan
8

Si no es anulable, ¿qué puede hacer el compilador cuando se inicializa el objeto?

El valor predeterminado de la cadena es nulo, por lo que

  1. o bien debe asignar un valor predeterminado de cadena en la declaración

    public string ServiceUrl { get; set; } = String.Empty;

  2. O inicialice el valor en el constructor predeterminado para deshacerse de la advertencia

  3. Usa el !operador (que no puedes usar)

  4. Que sea anulable como robbpriestley mencionó.

Athanasios Kataras
fuente
44
O agregue un constructor que acepte la URL del servicio como una cadena no anulable, por supuesto.
Jon Skeet
ServiceUrl'no puede ser = String.Empty. Hay otras propiedades de tipo complejo que no pueden ser nulas, por lo que utilicé defaultcomo: 'public MyClass MyProperty {get; conjunto; } = predeterminado! 'para detener la advertencia. Esta clase (y otras) es un constructor sin parámetros y últimamente se inicializa fuera del alcance de ctor.
M.Hassan
0

Otra cosa que puede ser útil en algunos escenarios:

[SuppressMessage("Compiler", "CS8618")]

Se puede usar encima del miembro o del tipo completo.


Otra cosa a tener en cuenta es agregar #nullable disableencima del archivo para deshabilitar la referencia anulable para todo el archivo.

Shimmy Weitzhandler
fuente