Reputation: 67193
I don't quite understand the following nullable warning.
As you can see, I have part of an expression where sheet
is not null, but sheet.Id
may be. But why can't I used sheet.Id.HasValue
to find out?
I also tried sheet.Id != null
, but that gives me a different warning.
Warning CS8625 Cannot convert null literal to non-nullable reference type.
How can I safely determine if sheet.Id
is not null?
This version actually compiles without warning. But I still don't understand why the other versions give me warnings.
public Worksheet? GetFirstWorksheet()
{
WorkbookPart? workbookPart = Document.WorkbookPart;
Workbook? workbook = workbookPart?.Workbook;
if (workbook != null)
{
Sheets? sheets = workbook.GetFirstChild<Sheets>();
Sheet? sheet = sheets?.Elements<Sheet>()
.FirstOrDefault();
if (sheet != null && sheet.Id?.Value != null)
return ((WorksheetPart)workbookPart!.GetPartById(sheet.Id!)).Worksheet;
}
return null;
}
Upvotes: 0
Views: 247
Reputation: 12988
You can combine
if (sheet != null && sheet.Id?.Value != null)
return ((WorksheetPart)workbookPart!.GetPartById(sheet.Id!)).Worksheet;
into a single equivalent expression:
if (sheet?.Id?.HasValue == true)
return ((WorksheetPart)workbookPart!.GetPartById(sheet.Id!)).Worksheet;
or
if (sheet?.Id?.Value != null)
return ((WorksheetPart)workbookPart!.GetPartById(sheet.Id!)).Worksheet;
I am not sure why the compiler is not smart enough to realize that the in some terms of your expression some of the fields could no longer be null.
By the way, depending on how far down the nullable chaining rabbit hole you want to go, you could rewrite the code from the images to look look something like this:
Worksheet? GetWorksheet(string name)
{
WorkbookPart? workbookPart = Document.WorkbookPart;
Worksheet? sheet = workbookPart?.Workbook
.GetFirstChild<Sheets>()?.Elements<Sheet>()
.Where(s => string.Compare(s.Name, name, true) == 0 && s.Id?.HasValue == true)
.Select(s => ((WorksheetPart) workbookPart!.GetPartById(s.Id!)).Worksheet)
.FirstOrDefault();
return sheet;
}
or
Worksheet? GetWorksheet(string name)
{
WorkbookPart? workbookPart = Document.WorkbookPart;
return workbookPart?.Workbook
.GetFirstChild<Sheets>()?.Elements<Sheet>()
.Where(s => string.Compare(s.Name, name, true) == 0 && s.Id?.HasValue == true)
.Select(s => ((WorksheetPart) workbookPart!.GetPartById(s.Id!)).Worksheet)
.FirstOrDefault();
}
Upvotes: 2