Podczas gdy studiowałem delegata, który jest w rzeczywistości klasą abstrakcyjną Delegate.cs
, zobaczyłem następującą metodę, której nie rozumiem
- Dlaczego wartość zwracana wykorzystuje,
?
mimo że jest to już typ referencyjny ( klasa ) ?[]?
znaczenie w parametrze
Czy możesz wytłumaczyć?
public static Delegate? Combine(params Delegate?[]? delegates)
{
if (delegates == null || delegates.Length == 0)
return null;
Delegate? d = delegates[0];
for (int i = 1; i < delegates.Length; i++)
d = Combine(d, delegates[i]);
return d;
}
c#
.net
null-coalescing-operator
nullable-reference-types
null-coalescing
snr - Przywróć Monikę
źródło
źródło
Odpowiedzi:
Wyjaśnienie krok po kroku:
params Delegate?[] delegates
- To tablica zerowalnychDelegate
params Delegate?[]? delegates
- Cała tablica może być zerowalnaPonieważ każdy parametr jest tego samego typu,
Delegate?
a zwracany jest indeksDelegate?[]?
tablicy, ma sens, że typem zwracanym jestDelegate?
inaczej, kompilator zwróciłby błąd tak, jakbyś się zatrzymywałint
z metody zwracającej ciąg.Możesz na przykład zmienić kod, aby zwracał taki
Delegate
typ:źródło
?
mimo że jest to już typ referencyjny (klasa)?
dokładnie ten sam powód, dla którego wartość argumentu używa?
. Jeśli zrozumiesz to drugie, automatycznie zrozumiesz pierwsze. Ponieważ metoda może zwracać null , podobnie jak parametr może przyjmować null . Oznacza to, że oba mogą zawierać wartość null .Since each parameter is of the type Delegate? and you return an index of the Delegate?[]? array, then it makes sense that the return type is Delegate?
Foo?
ma dobrąHasValue
właściwość, podczas gdyFoo
należy ją== null
sprawdzić (4) Informuje programistów, którzy czytają sygnaturę metody, że wartości null są możliwe, należy się spodziewać, i poprawny wynik. (5) Kod wygląda na napisany przez kogoś, kto bardzo lubi nullabness i jasno o tym mówiTypy zerowalne odniesienia są nowe w C # 8.0, wcześniej nie istniały.
To kwestia dokumentacji i sposobu generowania ostrzeżeń w czasie kompilacji.
Wyjątek „obiekt nieprzypisany do instancji obiektu” jest bardzo często spotykany. Jest to jednak wyjątek czasu wykonywania, który można częściowo wykryć już w czasie kompilacji.
Aby uzyskać regulację
Delegate d
, zawsze możesz zadzwonićco oznacza, że możesz to kodować, w czasie kompilacji nic się nie wydarzy. Może to powodować wyjątki w czasie wykonywania.
Chociaż nowy
Delegate? p
kodekswyświetli ostrzeżenie kompilatora.
CS8602: Dereference of a possibly null reference
chyba że napiszesz:co oznacza, dzwoń tylko wtedy, gdy nie ma wartości null.
Więc dokumentujesz, że zmienna może zawierać null lub nie. Wcześniej wyświetla ostrzeżenia i może uniknąć wielu testów na wartość NULL. To samo, co masz dla int i int ?. Wiesz na pewno, że jeden nie jest zerowy - i wiesz, jak przekonwertować jeden na drugi.
źródło
Delegate
nie jest zerowe. Udajesz, że wiesz na pewno (co w większości przypadków jest wystarczająco dobre).int
, nigdy nie może być zerowy. Jeśli maszDelegate
, może być zerowy (z różnych powodów, np. Refleksji). Zazwyczaj można bezpiecznie założyć, żeDelegate
(w C # 8 z włączoną NRT) nie ma wartości zerowej, ale nigdy nie wiadomo na pewno (gdzieint
na pewno wiemy).W C # 8 należy wyraźnie oznaczyć typy referencji jako zerowalne.
Domyślnie typy te nie mogą zawierać wartości null, podobnie jak typy wartości. Chociaż to nie zmienia sposobu działania rzeczy pod maską, narzędzie do sprawdzania typów będzie wymagać ręcznego wykonania tej czynności.
Podany kod jest refaktoryzowany do pracy z C # 8, ale nie korzysta z tej nowej funkcji.
Oto przykład zaktualizowanego kodu (nie działa, tylko pomysł) wykorzystującego tę funkcję. Uratowało to nas przed zerowym sprawdzeniem i nieco uprościło tę metodę.
źródło
those types are not able to contain null
, zwróć uwagę, że generuje ostrzeżenie kompilatora , a nie błąd. Kod będzie działał poprawnie (choć może generować wyjątki NullReferenceExceptions). Odbywa się to z myślą o kompatybilności wstecznej.