7

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

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;
}

我在下一行的“ac”对象上得到“对象引用未设置为对象的实例”。

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

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

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

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

在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源,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; }
}

始终在下面的行上引发异常,并且堆栈跟踪指向“ac”实例。

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

2 回答 2

6

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

这表明GetMyClasses()返回一个集合,该集合在任何与您的谓词匹配的元素之前都有一个空元素。这集合为空不同。

用这个检查它:

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

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

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

顺便说一句,ac它不是一个对象——它是一个变量(一个 lambda 表达式参数)。区分对象、变量和引用非常重要。一个对象永远不能为空——一个变量的值可以是。

于 2013-09-21T18:50:26.943 回答
0

首先是显而易见的东西:您正在访问

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

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

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

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

于 2013-09-21T19:06:01.220 回答