简体   繁体   中英

NullReference exception even though list items are not null

I must be missing something here, but I seem to have a List whose items are getting caught as null , even after I've checked and confirmed they were not.

My unit tests for my ASP.NET MVC project were throwing a NullReferenceException on a foreach loop, but I couldn't find any reason for it, so I threw a handful of checks into my code. To my surprise, the check statements don't catch any null values, but the exception persists. Here's the relevant code:

[HttpPost]
[ValidateAntiForgeryToken]
public PartialViewResult CreateSimilar(int rebateId, List<AddressInput> addresses, bool recdResults = false)
{
    List<RebateHeader> newRebates = new List<RebateHeader>();
    RebateHeader entity = null;

    int newId = -1;

    if (!recdResults)
    {
        var repo = _db as HeaderRepository;
        List<PotentialDuplicate> allDups = new List<PotentialDuplicate>();

        //A few checks for null objects to illustrate my point-------
        if (addresses == null)
            throw new ApplicationException("Addresses was null"); //Not thrown
        else
            System.Console.WriteLine("Addresses was not null"); //This line is hit

        foreach (AddressInput address in addresses)
        {
            if (address == null)
                throw new ApplicationException("Address was null"); //Not thrown
            else
                System.Console.WriteLine("Address was not null"); //This line is hit
        }

        var test = addresses[0];
        System.Console.WriteLine(test.City); //This line returns a value
        System.Console.WriteLine(test.State); //This line returns a value
        //End checks---------------------------------------------------

        foreach (AddressInput address in addresses) //NullReferenceException THROWN HERE
        {
            List<PotentialDuplicate> dups = repo.GetDuplicateAddresses(
                address.Address, address.City, address.State).ToList();
            if (dups.Count > 0)
            {
                allDups.AddRange(dups);
            }
        }

        if (allDups.Count > 0)
        {
            return PartialView("_AddressDialogPotentialDup", allDups);
        }
    }
    . . . //Additional code truncated
    return PartialView("_IndexNoPager", model);
}

I must be missing something here, but I'm not seeing it. Any ideas?

For further reference, here's the unit test that's failing:

[Test]
public void CreateSimilar_Adds_1_New_Record()
{
    EntryController controller = new EntryController(repository);
    List<AddressInput> addresses = new List<AddressInput> 
    {   
        new AddressInput 
    { 
        Address = "Duplicate St.", City = "Testville", State = "MN", 
        ClosingDate = null, Quarter = "115" 
    }
    };

    controller.CreateSimilar(1, addresses); //Unit test FAILS HERE

    Assert.AreEqual(4, repository.GetAll().Count());
    Assert.AreEqual(1, repository.Added.Count);
    Assert.AreEqual("Test Duplicate 1", repository.Added[0].Address);
}

UPDATE: In response to a comment below, here's my code for GetDuplicateAddresses :

public IEnumerable<PotentialDuplicate> GetDuplicateAddresses(
    string address, string city, string state)
{
    var result = new List<PotentialDuplicate>();

    using (SqlCommand cmd = new SqlCommand("dbo.GetDuplicateAddresses", (SqlConnection)this.Database.Connection))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@Address", address);
        cmd.Parameters.AddWithValue("@City", city);
        cmd.Parameters.AddWithValue("@State", state);

        cmd.Connection.Open();
        using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (reader.Read())
            {
                result.Add(new PotentialDuplicate
                {
                    OrigAddress = address,
                    RebateIdMatch = reader.GetInt32(0),
                    Address = reader.GetString(1),
                    MatchType = reader.GetString(2)
                });
            }

            return result;
        }
    }
}

And here's the stub I'm using in my unit test:

public IEnumerable<PotentialDuplicate> GetDuplicateAddresses(
    string address, string city, string state)
{
    var result = new List<PotentialDuplicate>();
    return result;
}

在做dups.Count()> 0之前,我将检查“ dups”是否为空。

As it turns out, the problem was with this cast:

var repo = _db as HeaderRepository;

I had to refactor some of my other code, and I changed this line slightly to raise an InvalidCastException if there's a similar issue in the future:

var repo = (IHeaderRepository)_db;

I hadn't even thought to check this, because the compiler was highlighting the foreach loop as the location of the exception. Thanks to Tim Southard and thepirat000 for pointing out that the code block inside the loop could cause the compiler to raise the exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM