question

JeffinAtl-3170 avatar image
0 Votes"
JeffinAtl-3170 asked JeffinAtl-3170 answered

How to check if List<T>.FirstOrDefault returns nothing

From the following code, patientlocallist is List<Patient>.

 var pat = patientlocallist.FirstOrDefault(p => p.PatientID == Convert.ToDouble(patient.PatientID));
 if (pat != null)//exist in the Active Patient List

When the patientlocallist.FirstOrDefault() returns nothing, an error occur from next line(if (pat!=null)) like following.
System.NullReferenceException:'Object reference not set to an instance of an object'

How to check if a List<T>.FirstOrDefault() returns nothing?


dotnet-csharp
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.


How did you determine that patientlocallist.FirstOrDefault() returns nothing?

Maybe another object was null, such as patientlocallist, p or patient.

0 Votes 0 ·

Place a breakpoint on if (pat != null) then when hit examine pat to see if it's null or not. Also, seems like if patient.PatientID would be the same type as whats in patientlocallist.

0 Votes 0 ·

pat is not null. and the type of patient.PatientID and the type of patient.PatientID and p.PatientID are the same.

0 Votes 0 ·

Did you try and set a breakpoint as suggested?

1 Vote 1 ·
Show more comments

I made a method instead of LINQ like following.

 PatientLocal pat = GetPatientLocal(patientlocallist, chartno);

However still the same error occur at if (pat != null).
pat is not null but error occur.
I can't figure out why this happen.

0 Votes 0 ·
karenpayneoregon avatar image
1 Vote"
karenpayneoregon answered DanielZhang-MSFT commented

Although your code appears correct it does not make sense. Usually the best course of action

  • Set a breakpoint, when the breakpoint is hit examine objects and values in Visual Studio local window.

  • If that does not help than (and this should be done if if no problems) create a unit test, mockup data and run the LINQ/Lambda to weed out issues.

Since a large majority of developers avoid writing unit test here is a test done in a Windows Form project. The first time we get null as identifier 5 does not exists while the second go around we are not null as id 3 exists.

 namespace WindowsFormsApp1
 {
     public partial class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();
         }
    
         private void GetPatientButton_Click(object sender, EventArgs e)
         {
             int identifier = 5;
             var pat = Operations.Patients.FirstOrDefault(patient => patient.PatientID == identifier);
             Console.WriteLine(pat == null ? $"{identifier} not found" : $"{pat.FirstName} {pat.LastName}");
    
             identifier = 3;
             pat = Operations.Patients.FirstOrDefault(patient => patient.PatientID == identifier);
             Console.WriteLine(pat == null ? $"{identifier} not found" : $"{pat.FirstName} {pat.LastName}");
         }
     }
    
     public class Patient
     {
         public int PatientID { get; set; }
         public string FirstName { get; set; }
         public string LastName { get; set; }
     }
    
     public class Operations
     {
         public static List<Patient> Patients => new List<Patient>()
         {
             new Patient() {PatientID = 1, FirstName = "Joe", LastName = "Jones"},
             new Patient() {PatientID = 2, FirstName = "Anne", LastName = "White"},
             new Patient() {PatientID = 3, FirstName = "Mary", LastName = "Smith"}
         };
     }
 }

Edit for the sake of argument for .NET Core this is how it's done.

  • First two are for those not use to the syntax are checking for null and if not null the variable after {} are populated

  • The last is null is clearer

Code

 namespace WindowsFormsApp2
 {
     public partial class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();
         }
    
         private void GetPatientButton_Click(object sender, EventArgs e)
         {
             int identifier = 5;
    
             if (Operations.Patients.FirstOrDefault(patient => patient.PatientID == identifier) is {} patientItem1)
             {
                 Debug.WriteLine($"{patientItem1.FirstName} {patientItem1.LastName}");
             }
             else
             {
                 Debug.WriteLine($"Failed to find {identifier}");
             }
                
    
             identifier = 3;
                
             if (Operations.Patients.FirstOrDefault(patient => patient.PatientID == identifier) is { } patientItem2)
             {
                 Debug.WriteLine($"{patientItem2.FirstName} {patientItem2.LastName}");
             }
             else
             {
                 Debug.WriteLine($"Failed to find {identifier}");
             }
    
             var pat = Operations.Patients.FirstOrDefault(patient => patient.PatientID == identifier);
             Debug.WriteLine(pat is null ? $"Failed to find {identifier}" : $"{pat.FirstName} {pat.LastName}");
         }
     }
    
     public class Patient
     {
         public int PatientID { get; set; }
         public string FirstName { get; set; }
         public string LastName { get; set; }
     }
    
     public class Operations
     {
         public static List<Patient> Patients => new List<Patient>()
         {
             new Patient() {PatientID = 1, FirstName = "Joe", LastName = "Jones"},
             new Patient() {PatientID = 2, FirstName = "Anne", LastName = "White"},
             new Patient() {PatientID = 3, FirstName = "Mary", LastName = "Smith"}
         };
     }
 }






· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I performed Unit test to verify LINQ statement and succeeded like following.
However the same LINQ doesn't work from my real project.


0 Votes 0 ·

Hi JeffinAtl-3170,
The above has provided detailed explanations and suggestions on the errors you encountered. In order to find the cause more quickly and accurately, I suggest you provide more and more detailed codes to reproduce the problem.
Best Regards,
Daniel Zhang

0 Votes 0 ·
oliverrc avatar image
0 Votes"
oliverrc answered JeffinAtl-3170 commented

Your check looks correct to me as T in the case is a class of type Patient I assume and hence it's default if the predicate returns false would be null.

If you are getting a null reference exception it may because either a record in the list contains a null PatientId or, because of lazy evaluation of LINQ statements, the list itself is null.

If PatientId is a nullable field (which would seem odd) then you may need to add a little defense to your predicate:

  var pat = patientlocallist.FirstOrDefault(p => p.PatientID != null && p.PatientID == Convert.ToDouble(patient.PatientID));
  if (pat != null)//exist in the Active Patient List
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

PatientID is not nullable and pat is not null, which means found data from patientlocallist.
Hence additional predicate(p.PatientID != null) doesn't work and the same error occur.

0 Votes 0 ·
cheong00 avatar image
0 Votes"
cheong00 answered JeffinAtl-3170 commented

See if you have the following line in your project file:

 <Nullable>enable</Nullable>

or the following in your current source file:

 #nullable enable

Alternatively you can just add "#nullable disable" on top of the code, or change "var" to "Patient?" to see if this will resolve the problem.

With .NET 5 nullable enabled, the "A != null" calls should be replaced with "A.HasValue" when compile. The possibly of compiler bug here is the only way I can think of that can raise NullReferenceException on that line.

It will be helpful if you can post your result here. Also please state the version of .NET runtime you're targeting (it's in your project file), and the runtime you've installed. If the reason is what I believe, then I'll bring attention to the language folks and see what they can do with "type detection with var".


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I'm using .NET 4.6.1 and can't find <Nullable> tag in the project file.
Already tried Patient instead of var but the result is the same.
I failed to attached file, so I show the part of the full detailed error.
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

 ************** Exception Text **************
 System.NullReferenceException: Object reference not set to an instance of an object.
    at Denttio.Message.MainForm.ImportProc(Double chartno) in C:\WorkDir\DenttioMessageApplication\CDMMsgView\MainForm.cs:line 1203
    at Denttio.Message.MainForm.MainForm_Load(Object sender, EventArgs e) in C:\WorkDir\DenttioMessageApplication\CDMMsgView\MainForm.cs:line 165
    at System.Windows.Forms.Form.OnLoad(EventArgs e)
    at System.Windows.Forms.Form.OnCreateControl()

..........

0 Votes 0 ·
DuaneArnold-0443 avatar image
0 Votes"
DuaneArnold-0443 answered

You are doing the correct check to see if an object is created from the Linq query of the List<T>.FirstOrDefault();

If (obj != null) // then the object is created based on the criteria to pull the object.

I like to use SingleOrDeFault().

If the object is pulled, that doesn't mean that a property within the object is not null that will throw the exception you are getting when you address properties within the pulled object.

If you wanted to check if the List<T> was null, then you would do a null check on the List<T>

if (List != null) //the List exist.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

JeffinAtl-3170 avatar image
0 Votes"
JeffinAtl-3170 answered

I found the reason is that the break point of debugger is not exactly working.
I mean the error occur not at the if (pat != null) but the different point even though I set the break point to that line.
I don't know why the break point doesn't work at the correct line.
I checked this by entering System.Diagnostics.Debugger.Break(); at the several position.
I deleted pdb files and compiled but still the break point doesn't work correctly.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.