Type de référence nul en C # 8 lors de l'utilisation de classes DTO avec un ORM

9

J'ai activé cette fonctionnalité dans un projet ayant des classes d'objets de transfert de données (DTO), comme indiqué ci-dessous:

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

Mais je reçois l'erreur:

CS8618: La propriété non nullable 'ServiceUrl' n'est pas initialisée. Envisagez de déclarer la propriété comme nullable.

Ceci est une classe DTO, donc je n'initialise pas les propriétés. Ce sera la responsabilité du code initialisant la classe pour s'assurer que les propriétés ne sont pas nulles.

Par exemple, l'appelant peut faire:

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

Ma question: comment gérer ces erreurs dans les classes DTO lorsque le contexte de nullité C # 8 est activé?

M.Hassan
la source
3
Lorsque vous effectuez l'initialisation de la construction comme vous le montrez, le constructeur par défaut s'exécute (initialisant ServiceUrl à sa valeur par défaut (qui, pour les chaînes, est nulle)). Ensuite, l'instruction initialize s'exécute. Si vous le souhaitez non nullable, il doit quitter tous les constructeurs initialisés
Flydog57
POCO ne signifie pas qu'il n'a pas de constructeur ou que les propriétés ne sont pas initialisées. Ça veut dire Plain Old C# Object. Juste un objet comme un autre, sans hériter d'aucune classe spéciale. Je soupçonne que vous avez une question différente . Comment créer des DTO -Data Transfer Objects
Panagiotis Kanavos
This should be the responsibility of the one initializing the class to ensure that the properties are non-nullla classe doit toujours être dans un état valide. Si ce nulln'est pas autorisé, la propriété ne doit jamais être nulle. Peut-être, au lieu d'une chaîne de base, vous devriez utiliser une classe spécialisée pour l'URL qui peut avoir une valeur de Noneou «manquant», comme la classe Option en F #. C # 8 vous permet d'écrire de telles classes et de les vérifier avec la correspondance de motifs
Panagiotis Kanavos
@Panagiotis Kanavos, La classe, dans mon cas, a une contrainte pour être un constructeur sans paramètre. Je dois donc utiliser la propriété Initializer: public string ServiceUrl { get; set; } = default! ;. J'espère que Roslyn aura à l'avenir un moyen de gérer l'initialisation tardive en dehors du champ d'application de ctor. J'utilisais MayBe <T> (comme la classe Option), mais je suis passé au type de référence nullable en c # 8 pour le nouveau code.
M.Hassan
Les TRN ne sont pas Maybes, en fait, les Maybes sont maintenant encore plus importants et plus faciles à utiliser. À condition bien sûr qu'ils soient construits en utilisant des idiomes C # qui les rendent faciles à travailler avec la correspondance de modèles
Panagiotis Kanavos

Réponses:

9

La solution suivante est recommandée par EF Core & EF6 voir

1) En initialisant null!avec l'opérateur pardonnant

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

2) Utilisation du champ de support:

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

M.Hassan
la source
La question mentionne qu'il ne peut pas utiliser l' !opérateur.
Athanasios Kataras
Je ne peux pas utiliser! avec le type, mais le lien que j'ai mentionné montre comment initialiser en utilisant null !. Il s'agit d'une solution de contournement. J'ai modifié la question.
M.Hassan
8

S'il n'est pas nullable, que peut faire le compilateur lorsque l'objet est initialisé?

La valeur par défaut de la chaîne est nulle, vous

  1. soit besoin d'attribuer une valeur par défaut de chaîne dans la déclaration

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

  2. Ou initialisez la valeur dans le constructeur par défaut afin de vous débarrasser de l'avertissement

  3. Utilisez l' !opérateur (que vous ne pouvez pas utiliser)

  4. Rendez-le nul comme l'a mentionné robbpriestley.

Athanasios Kataras
la source
4
Ou ajoutez un constructeur acceptant l'URL du service comme une chaîne non nullable, bien sûr.
Jon Skeet
ServiceUrl'ne peut pas être = String.Empty. Il existe d'autres propriétés de type complexe qui ne peuvent pas être nulles, j'ai donc utilisé defaultcomme: 'public MyClass MyProperty {get; ensemble; } = par défaut! 'pour arrêter l'avertissement. Cette classe (et d'autres) est un constructeur sans paramètre et est récemment initialisée en dehors de la portée de ctor.
M.Hassan
0

Une autre chose qui pourrait être utile dans certains scénarios:

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

Peut être utilisé au-dessus d'un membre ou d'un type entier.


Encore une autre chose à considérer est d'ajouter #nullable disableau-dessus du fichier pour désactiver la référence nullable pour tout le fichier.

Shimmy Weitzhandler
la source