Mam pytanie dotyczące Odnienny system Rodzaju odniesienia Dostępne od C # 8.

Przypuśćmy, że mamy klasę modelu domeny C # z uznanym właściwością typu odniesienia jak poniżej:

public class Person
{

    public string Name { get; set; }

    public Person(string name)
    {         
        Name = name;
    }
}

Do tej pory nie ma problemu. Ale uważam, że scenariusz prawdziwych światów, często chcę sprawdzić ważność nieruchomości, ponieważ jest to publiczna mutowalna nieruchomość i muszę upewnić się, że model niezmienny, gdy zmienia się nieruchomość.

public class Person
{
    private string _name;

    public string Name
    {
        get => _name;
        set => _name = value ?? throw new ArgumentNullException("Name is required.");
    }


    public Person(string name)
    {         
        Name = name;
    }
}

Następnie kompilator generuje ostrzeżenie CS8618, w zasadzie mówienie

"Non Nulable Field Name nie jest zainicjowany. Rozważ deklaruj pole jako nieważny typ".

Tak więc za każdym razem, gdy spotykam ostrzeżenie, że muszę załączyć konstruktora z następującą dyrektywą Pragma.

#pragma warning disable CS8618
public Person(string name)
{         
    Name = name;
}
#pragma warning restore CS8618

Ale myślę, że jest zbędny i nudny, aby zawsze to zrobić. Czy mogę coś nadużywać, czy jest lepszy sposób na napisanie takiej nieruchomości bez ostrzeżenia?

Oczywiście mogę zmienić typ właściwości na string? jako kompilator sugeruje, ale pojęcznie nie jest to akceptowalne jako rozwiązanie, ponieważ osoba powinna zawsze mieć nazwa bez Null i chcemy wyraźnie wyraźnie w stosunku do takiego niezmiennego stanu w klasie domeny.

Innym rozwiązaniem, które rozważałem, jest upuścić logikę walidacji argumentu i po prostu poleganie na nieważnym ostrzeżeniu kompilatora, ale nie zawsze jest to możliwe (mam na myśli często walidację innego niż kontrola NULL jest również wymagana.) Wymagane jest tylko ostrzeżenie w regularnych ustawieniach projektu, więc Nie sądzę, że to dobre rozwiązanie.

15
Ryo Asai 16 marzec 2020, 09:19

2 odpowiedzi

Najlepsza odpowiedź

Na razie możesz uniknąć tego ostrzeżenia, inicjując pole _name za pomocą wartości domyślnej z Null-wybaczający operator !, jak

private string _name = default!;

Lub

private string _name = null!;

Istnieje również otwarty Wydanie GitHub dla tego.

Możesz również zadeklarować _name jako string? i określić, że wartość powrotna Name właściwości nie może być null (Nawet jeśli string? Pozwala na to), Korzystanie z {{X5 }} atrybut

private string? _name;

[NotNull]
public string? Name
{
    get => _name;
    set => _name = value ?? throw new ArgumentNullException("Name is required.");
}

Powinno być w porządku, w przeciwnym razie kompilator pokazuje ostrzeżenie przed logiką walidacyjnej odbędzie się w seter

set => _name = value ?? throw new ArgumentNullException("Name is required.");

Rozważmy następujący kod

var person = new Person(null);

W tym przypadku dostaniesz

OSTRZEŻENIE CS8625: Nie można konwertować null dosłownego do nieważnego typu odniesienia.

Przed ArgumentNullException zostanie rzucony.

Jeśli ustawisz <TreatWarningsAsErrors>true</TreatWarningsAsErrors> lub traktuj CS8625 ostrzeżenie jako błąd, wyjątek nie zostanie rzucony

11
Pavel Anikhouski 17 marzec 2020, 07:40

Na podstawie To:

Ostrzeżenia dotyczące zainicjowanych pól Q: Dlaczego ostrzeżenia zgłaszane są dla dziedzin, które są inicjalizowane pośrednio przez konstruktora lub na zewnątrz konstruktora?

Odp.: Kompilator rozpoznaje pola wyraźnie wyraźnie przydzielone tylko w obecnym konstruktorze, a ostrzega dla innych dziedzin zadeklarowanych jako nieuznane. To ignoruje inne sposoby, w jaki pola mogą być inicjowane, takie jak metody fabryczne, metody pomocnicze, osadniki nieruchomości i inicjalizatory obiektów. Będziemy zbadać rozpoznawanie wspólnych wzorców inicjalizacji, aby uniknąć niepotrzebnych ostrzeżeń.

Więc z tym powiedziano na razie przenoszenie zadania bezpośrednio do konstruktora, jest jedynym możliwym sposobem. I na pewno korzystanie z dyrektywy Pragma wydaje się w porządku dla tego IMO.

3
Salah Akbari 16 marzec 2020, 06:49