创建空列表时可能导致空引用异常的原因是什么?

时间:2014-07-19 08:22:54

标签: c# entity-framework nullreferenceexception

更新

这似乎是在Visual Studio中单步执行方法而不是与Linq语句的内容直接相关的问题。为了省略这部分代码,我正在使用调试器跳过一些耗时的方法 - 如果我不是跳过它们,让它们只是在第一行返回,那么错误就会消失。

我有一个以下代码的可重复示例,在最后一行抛出空引用异常:

            List<Product> testList = new List<Product>
            {
                new Product
                {
                    Sku = "sku"
                }
            };
            string sku = testList.First().Sku;

            var simpleQuery = testList.Select(p => p.Sku);

            List<string> skus = simpleQuery.ToList();

但是,如果我跳过一个方法的调试器(即使我跳过的方法看起来像这样),这只会发生:

    private bool DoSeomthing()
    {
        return false;
    }

我有兴趣知道是否有人可以对此进行再版或有任何想法可能导致它...

原始

我在相对常规的代码中偶然发现了一些相当奇怪的行为,令人困惑,我不确定如何进一步调查。

似乎当我尝试实例化List然后在多个LINQ查询中使用该列表时,初始实例化会抛出空引用异常。

此代码的第一行抛出'对象引用未设置为对象的实例。'

我已经注释掉了实际的存储库代码,但只是使用新的List()仍然会抛出。

List<Product> testProducts = new List<Product>();
                               // _repo.Products().ToList();


List<Product> deleteProducts = 
    testProducts .Where(p => !(importProducts.Select(ip => ip.Sku).Contains(p.Sku))).ToList();

List<Product> addedProducts = //new List<Product>();
    importProducts.Where(p => !(testProducts.Select(ip => ip.Sku).Contains(p.Sku))).ToList();

如果我将addedProducts的声明更改为新的List而不是linq查询,则代码运行正常。

行怎么样:

List<Product> testProducts = new List<Product>();

抛出空引用异常?

可能是一些奇怪的编译器优化错误或什么?为什么会这样?可以做些什么来解决它?

我正在使用Visual Studio 2013,而Product是Entity Framwork版本6.0.0.0对象。我已经尝试恢复Visual Studio,清理解决方案,重新启动机器 - 但没有快乐。像往常一样在这种奇怪的情况下,我确信这个完全相同的代码上周正在运作......

3 个答案:

答案 0 :(得分:4)

通常情况下,我发现当我被实体框架NullReferenceException难倒时,它不是因为我正在做什么返回 null,因此我试图引用一个null 的属性。

例如,如果找不到任何项,FirstOrDefault()将返回null,但是:

string Name = db.Items.FirstOrDefault(x => x.Id == 1).Name;

将抛出NulReferenceException,因为当从调用返回null时,它无法获取它的Name属性。

我的建议是将嵌套调用拆分为单独的变量并将其传入,这样就可以确定哪个表达式实际返回null。

另一件令人困惑的事情是EF的延迟执行 - 通常抛出错误的行是而不是引起它的行,它只是执行错误语句时发生的不幸行。

答案 1 :(得分:1)

我遇到了类似的问题,这是我的代码:

if (true)
{
    List<Product> addedProducts;
    addedProducts = new List<Product>();    // Works
}
else
{
    List<Product> addedProducts;
    addedProducts = new List<Product>();    // Throw Exception
}

解决方案是在方法开头移动声明:

List<Product> addedProducts;
if (true)
    addedProducts = new List<Product>();    // Works
else
    addedProducts = new List<Product>();    // Works

编译器允许您在同一方法的不同范围内声明两个具有相同名称的变量,但是当您尝试在else中初始化时,您会获得NullReferenceException

您还可以查看生成的IL(并将其包含在您的问题中)。

答案 2 :(得分:0)

  

如果我将addedProducts的声明更改为新的List而不是   一个linq查询然后代码运行得很好。

这个错误很可能就在这句话中。

检查此语句中的所有对象,并确保它们已实例化。你确定anotherTestProducts不是空的吗?

有时候,当引发错误时,VS突出显示的内容可能会产生误导。