System.linq.Enumerable命名空间的FirstOrDefault()方法抛出NullReferenceException

时间:2013-09-21 18:48:50

标签: c# .net linq

我有一个用户定义对象类型的静态只读集合,它初始化如下。

private static readonly List<MyClass> obj = new List<MyClass>();

另一个公用事业方法填充此集合并返回集合。

public static List<MyClass> GetMyClasses(){

// some code for DB calls goes here
// in a loop based on recordset, i fill the collection like below
obj.Add(new MyClass(){// my class property settings based on DB values});

// finally return the collection
return obj;
}

我得到的对象引用没有设置为对象的实例&#39; on&#39; ac&#39;对象在下面。

var cl = TestClass.GetMyClasses().FirstOrDefault(ac => ac.name == "myname")

我想知道为什么&#39; ac&#39;这里的对象是NULL,即使我们的集合是空的,根据MSDN,FirstOrDefault如果找不到匹配项,也应该为引用类型返回NULL。

有人可以帮助我理解我在这里缺少的东西吗?在今天开始抛出异常之前,相同的代码在几个月内完美运行。即使在今天,相同的代码在其他服务器上运行良好也没有问题。

出于安全原因,我无法发布整个异常堆栈跟踪,但它指向IL代码下面

在System.Linq.Enumerable.FirstOrDefault [TSource](IEnumerable`1 source,Func`2谓词)

使用类似问题的示例代码更新问题。

public static class DemoDataAccess
    {
        private static readonly List<MyTestClass> classes
            = new List<MyTestClass>();

        public static IList<MyTestClass> GetMyClasses()
        {
            using (var cnn = new SqlConnection(@"connection string goes here"))
            {
                cnn.Open();
                using (var cmd = new SqlCommand("SP Name", cnn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            classes.Add(new MyTestClass()
                                       {
                                         Id = Convert.ToInt32(rdr["id"]),
                                         Name = Convert.ToString(rdr["name"])
                                       });
                        }
                    }
                }
            }

            return classes;
        }
    }


public class MyTestClass
{
    public int Id { get; set; }
    public string Name { get; set; }
}

在线下方抛出一致的异常,堆栈跟踪指向&#39; ac&#39;实例

var obj = DemoDataAccess
             .GetMyClasses()
             .FirstOrDefault(ac => ac.Name == "something");

2 个答案:

答案 0 :(得分:5)

  

我想知道为什么'ac'对象在这里是NULL,即使我们的集合是空的,因为根据MSDN,FirstOrDefault如果找不到匹配则应该为引用类型返回NULL。

这表明GetMyClasses()返回一个集合,该集合在与谓词匹配的任何元素之前具有null元素。那个和集合是空的一样。

用这个检查:

int nullElements = TestClass.GetMyClasses().Count(ac => ac == null);

我强烈怀疑你会发现nullElements非零。

如果那个问题,那么你应该努力提供一个简短但完整的程序,你可以发布。您不需要发布真实代码 - 只是显示相同问题的代码。看到这样的代码我会感到非常惊讶 - 看起来你更有可能在开始时以某种方式得到一个null元素,这肯定会解释你所看到的异常。

另外,ac不是对象 - 它是变量(lambda表达式参数)。区分对象,变量和引用非常重要。对象永远不能为null - 变量的值可以是。

答案 1 :(得分:0)

首先是明显的东西: 您正在访问

...ac.name == "..."

此时,如果ac为null,您将获得空指针异常。 这也意味着,由于某种原因,您的集合包含NULL元素。

现在,根据你复制的代码,不可能有NULL元素,这不是完整的代码,并且有一个小故障,它会在列表中插入NULL,或者你的内容中必须有其他地方实际更改集合并将元素设置为null的应用程序。

:编辑:在填充和读取数组之间是否有任何异步或并行代码执行?