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?


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));
        }


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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.