Co to jest nieznana nullability w C # 8?

12

W C # 8.0 możemy mieć typy zerowalne. Dokumenty stwierdzają, że istnieją 4 rodzaje zerowalności. Pierwsze 3 są dość jasne, ale nie rozumiem sensu „nieznane”. Dokumenty mówią, że używa się go z rodzajami, ale kiedy próbuję wywołać metodę na nieograniczonej zmiennej typu T w rodzajach, to po prostu ostrzega, jakby typ był zerowalny. Nie widzę różnicy między nieznanym a zerowalnym. Dlaczego istnieje nieznane? Jak to się objawia?

Stilgar
źródło

Odpowiedzi:

12

Zastosuj następującą metodę ogólną:

public static T Get<T>(T value)
{
    return value;
}

Jeśli nazywamy to tak Get<string>(s), zwrot nie jest zerowalny, a jeśli tak Get<string?>(s), to jest zerowalny.

Jednak jeśli wywołujesz go za pomocą ogólnego argumentu, takiego jak Get<T>(x)i Tnie został rozwiązany, na przykład jest to ogólny argument dla ogólnej klasy, taki jak poniżej ...

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // is result nullable or non-nullable? It depends on T
    }
}

W tym przypadku kompilator nie wie, czy ostatecznie zostanie wywołany z typem zerowalnym lub zerowalnym.

Istnieje nowy typ ograniczenia, którego możemy użyć do zasygnalizowania, że Tnie może być zerowy:

public static T Get<T>(T value) where T: notnull
{
    return value;
}

Jednak tam, gdzie Tjest nieograniczone i wciąż otwarte, nullability jest nieznany.

Jeśli te niewiadome zostały potraktowane jako zerowalne, możesz napisać następujący kod:

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // reassign result to null, cause we we could if unknown was treated as nullable
        result = null;
    }
}

W przypadku, gdy Tnie było zerowalne, powinniśmy otrzymać ostrzeżenie. Tak więc w przypadku nieznanych typów zerowania chcemy ostrzeżeń podczas dereferencji, ale także ostrzeżeń o potencjalnym przypisaniu null.

Stuart
źródło
Kiedy zrobię var wynik = Test.Get <T> (x); result.ToString (); kompilator skarży się na dereferencjowanie potencjalnie zerowej wartości. Nie rozumiem, jak nieznane różni się od po prostu zerowania w tym przypadku.
Stilgar
1
Pod względem ostrzeżeń zachowują się tak samo, ale są semantycznie różne. Można powiedzieć, że różnica jest akademicka, a jeśli o to ci chodzi, to zgadzam się.
Stuart,
1
Wciąż chciałbym wiedzieć, dlaczego wprowadzono tę różnicę. Dziwne wydaje się wprowadzenie takiego rozróżnienia w języku do celów akademickich.
Stilgar
Mój zły, po prostu ponownie przeczytaj specyfikację, zaktualizuj odpowiedź, ostatnia część to wyjaśnia.
Stuart,
1
Ach, to bardziej tak
Stilgar,