Nullbarer Referenztyp in C # 8 bei Verwendung von DTO-Klassen mit einem ORM

9

Ich habe diese Funktion in einem Projekt mit DTO-Klassen (Data Transfer Object) aktiviert, wie unten angegeben:

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

Aber ich bekomme den Fehler:

CS8618: Die nicht nullbare Eigenschaft 'ServiceUrl' ist nicht initialisiert. Erwägen Sie, die Eigenschaft als nullbar zu deklarieren.

Dies ist eine DTO-Klasse, daher initialisiere ich die Eigenschaften nicht. Dies liegt in der Verantwortung des Codes, der die Klasse initialisiert, um sicherzustellen, dass die Eigenschaften nicht null sind.

Der Anrufer kann beispielsweise Folgendes tun:

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

Meine Frage: Wie gehe ich mit solchen Fehlern in DTO-Klassen um, wenn der Nullfähigkeitskontext von C # 8 aktiviert ist?

M. Hassan
quelle
3
Wenn Sie die Konstruktionsinitialisierung wie gezeigt durchführen, wird der Standardkonstruktor ausgeführt (Initialisierung von ServiceUrl auf seinen Standardwert (der für Zeichenfolgen null ist)). Anschließend wird die Anweisung initialize ausgeführt. Wenn Sie möchten, dass es nicht nullbar ist, müssen alle initialisierten Konstruktoren beendet werden
Flydog57
POCO bedeutet nicht, dass es keinen Konstruktor hat oder dass die Eigenschaften nicht initialisiert werden. Es bedeutet Plain Old C# Object. Nur ein Objekt wie jedes andere, ohne von einer speziellen Klasse zu erben. Ich vermute, Sie haben eine andere Frage. So erstellen Sie DTOs -Data Transfer Objects
Panagiotis Kanavos
This should be the responsibility of the one initializing the class to ensure that the properties are non-nullDie Klasse sollte immer in einem gültigen Zustand sein. Wenn dies nullnicht zulässig ist, sollte die Eigenschaft niemals null sein. Vielleicht sollten Sie anstelle einer einfachen Zeichenfolge eine spezielle Klasse für die URL verwenden, die den Wert Noneoder "Missing" haben kann, wie die Option-Klasse in F #. Mit C # 8 können Sie solche Klassen schreiben und sie mit Mustervergleich überprüfen
Panagiotis Kanavos
@Panagiotis Kanavos, Die Klasse hat in meinem Fall die Einschränkung, ein parameterloser Konstruktor zu sein. Also muss ich Property Initializer verwenden : public string ServiceUrl { get; set; } = default! ;. Ich hoffe, dass Roslyn in Zukunft eine Möglichkeit hat, die späte Initialisierung außerhalb des Bereichs von ctor zu handhaben. Ich habe MayBe <T> (wie die Optionsklasse) verwendet, aber für den neuen Code in c # 8 auf nullable Reference Type umgestellt.
M. Hassan
NRTs sind nicht Maybes, in der Tat, Maybes sind jetzt noch mehr wichtige und einfacher zu bedienen. Vorausgesetzt natürlich, sie werden mit C # -Idiomen erstellt, die es ihnen leicht machen, mit Mustervergleich zu arbeiten
Panagiotis Kanavos

Antworten:

9

Die nächste Lösung wird von EF Core & EF6 empfohlen, siehe

1) Durch Initialisieren mit null!mit verzeihendem Bediener

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

2) Verwenden des Hintergrundfelds:

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

M. Hassan
quelle
In der Frage wurde erwähnt, dass er den !Operator nicht verwenden kann .
Athanasios Kataras
Ich kann nicht benutzen! mit Typ, aber der Link, den ich erwähnte, zeigt, wie man mit null! initialisiert. Es ist eine Problemumgehungslösung. Ich habe die Frage geändert.
M. Hassan
8

Wenn es nicht nullbar ist, was kann der Compiler dann tun, wenn das Objekt initialisiert wird?

Der Standardwert der Zeichenfolge ist null

  1. Sie müssen entweder einen Standardwert für die Zeichenfolge in der Deklaration zuweisen

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

  2. Oder initialisieren Sie den Wert im Standardkonstruktor, damit Sie die Warnung entfernen

  3. Verwenden Sie den !Operator (den Sie nicht verwenden können)

  4. Machen Sie es nullbar, wie von robbpriestley erwähnt.

Athanasios Kataras
quelle
4
Oder fügen Sie einen Konstruktor hinzu, der die Service-URL natürlich als nicht nullfähige Zeichenfolge akzeptiert.
Jon Skeet
ServiceUrl'kann nicht sein = String.Empty. Es gibt andere Eigenschaften von komplexem Typ, die nicht null sein können, daher habe ich defaultFolgendes verwendet : 'public MyClass MyProperty {get; einstellen; } = Standard! 'um die Warnung zu stoppen. Diese Klasse (und andere) ist ein parameterloser Konstruktor und wurde kürzlich außerhalb des Bereichs von ctor initialisiert.
M. Hassan
0

Eine andere Sache, die in einigen Szenarien nützlich sein könnte:

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

Kann über dem Element oder dem gesamten Typ verwendet werden.


Eine weitere zu berücksichtigende Sache ist das Hinzufügen #nullable disableüber der Datei, um die nullfähige Referenz für die gesamte Datei zu deaktivieren.

Shimmy Weitzhandler
quelle