Tipo de referência anulável em C # 8 ao usar classes DTO com um ORM

9

Eu ativei esse recurso em um projeto com classes de objeto de transferência de dados (DTO), conforme indicado abaixo:

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

Mas eu recebo o erro:

CS8618: A propriedade não anulável 'ServiceUrl' não foi inicializada. Considere declarar a propriedade como anulável.

Esta é uma classe DTO, por isso não estou inicializando as propriedades. Isso será de responsabilidade do código que inicializou a classe para garantir que as propriedades sejam não nulas.

Por exemplo, o chamador pode fazer:

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

Minha pergunta: como lidar com esses erros nas classes DTO quando o contexto de nulidade do C # 8 está ativado?

M.Hassan
fonte
3
Quando você faz a inicialização da construção da maneira que mostra, o construtor padrão é executado (inicializando ServiceUrl com seu valor padrão (que, para cadeias de caracteres, é nulo)). Em seguida, a instrução de inicialização é executada. Se você deseja que ele não nulo, ele precisa sair todos os construtores inicializado
Flydog57
POCO não significa que não tem construtor ou que as propriedades não foram inicializadas. Isso significa Plain Old C# Object. Apenas um objeto como outro qualquer, sem herdar de nenhuma classe especial. Eu suspeito que você tem uma pergunta diferente . Como criar DTOs -Data Transfer Objects
Panagiotis Kanavos
This should be the responsibility of the one initializing the class to ensure that the properties are non-nulla classe deve estar sempre em um estado válido. Se nullnão for permitido, a propriedade nunca deve ser nula. Talvez, em vez de uma string básica, você deva usar uma classe especializada para a URL que possa ter um valor de Noneou `Missing`, como a classe Option em F #. C # 8 permite que você escreva tais classes e verificá-los com correspondência de padrão
Panagiotis Kanavos
@ Panagiotis Kanavos, A classe, no meu caso, tem uma restrição de ser um Construtor sem parâmetros. Então eu tenho que usar a propriedade Initializer: public string ServiceUrl { get; set; } = default! ;. Espero que Roslyn possa ter no futuro uma maneira de lidar com a inicialização tardia fora do escopo do ctor. Eu estava usando MayBe <T> (como a classe Option), mas mudei para Tipo de referência anulável em c # 8 para o novo código.
`` #
Os NRTs não são Maybes, na verdade, agora os Maybes são ainda mais importantes e fáceis de usar. Desde, é claro que eles estão compilação usando C # expressões que os tornam fácil trabalhar com correspondência de padrão
Panagiotis Kanavos

Respostas:

9

A próxima solução é recomendada pelo EF Core e EF6, consulte

1) Inicializando null!com o operador que perdoa

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

2) Usando o campo de apoio:

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

M.Hassan
fonte
A pergunta mencionou que ele não pode usar o !operador.
Athanasios Kataras
Eu não posso usar! com type, mas o link que eu mencionei mostra como inicializar usando null !. É uma solução alternativa. Eu modifiquei a pergunta.
M.Hassan
8

Se não for anulável, o que o compilador pode fazer quando o objeto for inicializado?

O valor padrão da sequência é nulo, portanto, você

  1. precisa atribuir um valor padrão de sequência na declaração

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

  2. Ou inicialize o valor no construtor padrão para que você se livre do aviso

  3. Use o !operador (que você não pode usar)

  4. Torne-o nulo como robbpriestley mencionado.

Athanasios Kataras
fonte
4
Ou adicione um construtor que aceite a URL do serviço como uma sequência não anulável, é claro.
Jon Skeet
ServiceUrl'não pode ser = String.Empty. Existem outras propriedades do tipo complexo que não podem ser nulas, então eu usei defaultcomo: 'public MyClass MyProperty {get; conjunto; } = padrão! 'para parar o aviso. Essa classe (e outras) é construtora sem parâmetros e é inicializada recentemente fora do escopo do ctor.
M.Hassan
0

Outra coisa que pode ser útil em alguns cenários:

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

Pode ser usado em cima do membro ou do tipo inteiro.


Outra coisa a considerar é adicionar #nullable disableno topo do arquivo para desativar a referência anulável para todo o arquivo.

Shimmy Weitzhandler
fonte