Use of unassigned local variable - dlaczego w C# nullable musi mieć przypisaną wartość null skoro jest nullable?

0

Witam.
Natknąłem się na pewien problem, którego wcześniej nie było.

Customer? customer;
BankEvent be = new BankEvent();

if (document.VatDocument.CustomerId.HasValue)
  customer = await _customersReader.GetCustomerById(document.VatDocument.CustomerId.Value);

if(customer != null) // <== W tym miejscu mam błąd "'customer' may be null here. Use of unassigned local variable 'customer'"
{
  be.BankNameId = customer.BankNamesId;
  be.AccountNumber = customer.BankAccountNumber;
}

Dlaczego C# wymaga, abym zrobił Customer? customer = null;? Czy mój zapis nie znaczy tego samego? Ja wiem, że 'customer' może być null w tym miejscu... Dlatego sprawdzam czy nie jest 😂

0

@AdamWox:

C# nullable to zagadnienie w innym wymiarze niż inicjowanie zmiennych (jakichkolwiek).
Zmienne w kodzie (nie pola w obiekcie) maja być zainicjowane, tak przyjęli konstruktorzy języka.

ps. zdziwiony jestem pytajnikiem/nullable przy chyba dośc dużym obiekcie klasy, pn Customer.
Bo to obiekt KLASY czy STRUKTURY? Zmnienne na instancje klasy są z mocy ustawy nullable (bo są referencjami), zmienne struktur nie są, bo są wartością

Urodą C# jest bardzo mocne rozdzielenie tych dwóch pojęć (o wiele głębsze niż C++). Ale całe moje myślenie idzie ścieżką, że struct C# są niewielkie i złożone z typó prostych (prawie prostych), jak np MyCurrency, WorkingDateWithShift itd, i cały biznes z wartościami ma sens.

0

Dałem pytajnik/nullable do customer, ponieważ await _customersReader.GetCustomerById(document.VatDocument.CustomerId.Value); zwaraca nullable. Usunięcie pytajnika ze zmiennej customer powoduje, że VS podkreśla na zielono z opisem Converting null literal or possible null value to non-nullable type. Drażni mnie to zwyczajnie. Idąc dalej... Usunę pytajnik z GetCustomerById to dzieje się podobnie, ponieważ EF, za pomocą FirstOrDefaultAsync() zwraca nullable i kółeczko się zamyka. To jest klasa, encja z bazy.

0
AdamWox napisał(a):

Dałem pytajnik/nullable do customer, ponieważ await _customersReader.GetCustomerById(document.VatDocument.CustomerId.Value); zwaraca nullable. Usunięcie pytajnika ze zmiennej customer powoduje, że VS podkreśla na zielono z opisem Converting null literal or possible null value to non-nullable type. Drażni mnie to zwyczajnie. Idąc dalej... Usunę pytajnik z GetCustomerById to dzieje się podobnie, ponieważ EF, za pomocą FirstOrDefaultAsync() zwraca nullable i kółeczko się zamyka. To jest klasa, encja z bazy.

No i?
FirstOrDefaultAsync() zwróci obiekt lub null. Jeśli _customersReader zwraca obiekt Customer to możesz zrobić return null i też zadziała. Normalna sprawa. Nie musisz rypac '?'

0

W jakimś celu VS to podkreśla. Czy nie "rypiąc" pytajników nie odbije się to na mnie później? Ma to jakieś znaczenie w sprawdzaniu/zwracaniu null? Czy to jest idiotoodporny feature, który ma nakierować programistę na możliwe konsekwencje, ale nie jest must do?

0

Ale pokaż kod co podkreśla?. Bo jeśli coś robisz po drodze przed zwróceniem to może podkreślać.
Ale jeśli masz tylko return await db.Customers.FirstOrDefaultAsync() to nie powinno nic podkreślać

0

Bez ?

public async Task<Customer> GetCustomerById(int id)
{
  return await _db.Customers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id); // <== Possible null reference return
}

Jeśli zmienię na Task<Customer?> to nie ma podkreślenia. To nie jest błąd, to jest tylko warning. Ja wiem, że warningi się ignoruje, ale chyba po coś to jest. Skoro to co napisał @ZrobieDobrze

Zmnienne na instancje klasy są z mocy ustawy nullable (bo są referencjami)

To dlaczego VS traktuje to jako warning? Jakie mogą być tego konsekwencje, że nie dam ?

2

Czy to jest idiotoodporny feature, który ma nakierować programistę na możliwe konsekwencje, ale nie jest must do?
Jakie mogą być tego konsekwencje, że nie dam ?

IMO Tak. Konsekwencja będzie taka, że jako programista możesz "zapomnieć", że ta wartość może być null. A tak będziesz widział, bo masz to jawnie zaznaczone. Cały ten cyrk z podkreślaniem nullowalności w .NET 6 wynika z tego ;)

BTW, możesz to wyłączyć, usuwając <Nullable> w .csproj.

Dokumentacja mówi:

Nullable reference types refers to a group of features introduced in C# 8.0 that you can use to minimize the likelihood that your code causes the runtime to throw System.NullReferenceException.

2

W nowszych wersjach C# Microsoft wprowadził oznaczanie wprost typów referencyjnych jako nullable. Po to, żeby zachęcić do świadomego używania nulla i ograniczania przez to wyjątków związanych z brakiem referencji. I prawdopodobnie w VS2022 domyślnie włączona jest flaga, która sprawdza czy używasz nulla tylko dla zmiennych oznaczonych '?'. Można nawet ustawić, żeby był to błąd kompilacji kiedy będzie ktoś ustawiał null na zmiennej, która nie była na to gotowa. Stąd ten warning.

Ktos mnie ubiegł :D

0

@szydlak: Nie, to nie jest preview. Jest to EF Core w .NET 6 WebAPI.

@Ktos: Ok, faktycznie usunięcie wpisu <Nullable> z .csproj powoduje, że nie podkreśla mi już tego

Reasumując - dobrze mieć włączone nullable i stosować się do tego co VS podkreśla, aby nie było cyrków w przyszłości. Chyba każdego denerwuje null reference exception, bo coś przeoczył 🤔

1 użytkowników online, w tym zalogowanych: 0, gości: 1