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

JeffinAtl 161 Reputation points
2021-06-28T04:50:48.12+00:00

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?

Developer technologies | C#
{count} votes

Accepted answer
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2021-06-30T01:47:35.353+00:00

    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"}
            };
        }
    }
    
    1 person found this answer helpful.

4 additional answers

Sort by: Most helpful
  1. Oliver Rivett-Carnac 6 Reputation points
    2021-06-28T07:54:14.413+00:00

    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
    

  2. cheong00 3,486 Reputation points Volunteer Moderator
    2021-06-29T09:05:46.5+00:00

    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".


  3. Duane Arnold 3,216 Reputation points
    2021-06-29T21:37:14.55+00:00

    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.

    0 comments No comments

  4. JeffinAtl 161 Reputation points
    2021-07-02T02:54:42.113+00:00

    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.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.