尝试将对象添加到类中的列表时出现“对象引用未设置为对象的实例”错误 [重复]

"Object reference not set to an instance of an object" error when trying to add objects to a list inside a class [duplicate]

提问人:thanby 提问时间:5/2/2014 最后编辑:John Saundersthanby 更新时间:11/21/2017 访问量:24153

问:

我定义了一些自定义类,其中包括其他类的列表,如下所示:

public class Unit
{
    public string Name { get; set; }
    public List<Group> Contains { get; set; }
}

public class Group
{
    public string Name { get; set; }
    public Type Type { get; set; }
    public int Number { get; set; }
}

public static Type basic_1 = new Type() { Name = "basic_1", Number = 1, Cost = 13 };

基本思想是你有一个单元,其中包含一个组列表,每个组都有不同的类型。该类型包含特定属性,而包含这些属性的类本质上是组织属性。

然后,我尝试开始构建这些类,如下所示:

Unit unit1 = new Unit() { Name = "Unit 1" };
Group group1 = new Group() { Name = "Group 1", Number = 10, Type = basic_1 };
unit1.Contains.Add(group1);

但是在这里我收到错误(在方法上)“对象引用未设置为对象的实例”。查看调试器中的局部变量,我可以看到 和 都已成功创建,并且包含它应该包含的所有值,但为 null。AddUnitGroupTypegroup1Typeunit1.Contains

我做错了什么?仅供参考,我以前从未做过这样的事情,所以我什至不知道这是否可能,但到目前为止它似乎工作正常。

C# List 对象 NullReferenceException

评论

1赞 John Saunders 5/2/2014
几乎所有的情况都是一样的。有关一些提示,请参阅“什么是 .NET 中的 NullReferenceException?”NullReferenceException
0赞 asunrey 5/2/2014
如果您不想更改您的班级,只需在列表中新建即可。单元1。包含 = new List<Group>();
0赞 Crono 5/2/2014
我建议不要制作可写属性。作为只读属性公开的列表仍然可以从类外部进行修改(例如,您可以在其中添加和删除内容),这将防止外部代码将实例设置为 null 或其他列表。哦,也不要说出它的名字。ContainsContains

答:

4赞 Crono 5/2/2014 #1

类中的列表永远不会被实例化。ContainsUser

您可能希望将类更改为以下类:User

public class Unit
{
    public string Name { get; set; }

    List<Group> list = new List<Group>();

    public List<Group> Contains
    {
        get { return list; }
    }
}

正如你所看到的,该属性现在只返回一个列表实例,该实例当然可以修改,但永远不会重新受到影响。很可能,这就是你想要的。Contains

虽然这有点超出了您的问题范围,但我建议您将属性重命名为ContainsGroups

评论

0赞 thanby 5/2/2014
找不到类型或命名空间名称“var” - 请原谅我的 n00bishness,但我缺少什么来允许我使用它?它在方法中工作正常,但在类中不起作用。
0赞 mason 5/2/2014
通过在属性上使用私有集运算符,可以在不需要私有字段的情况下完成相同的操作。简化代码。public List<Group> Contains {get; private set;}
0赞 Crono 5/2/2014
@mason,但随后您需要一个构造函数来实例化列表。:)
13赞 mason 5/2/2014 #2

你永远不会被初始化,所以当你尝试访问它时,你会得到一个空引用异常。基本上所有 null 引用异常都是相同的,您正在尝试使用为 null 的对象。List<Group> Contains

在本例中,我们只需添加一个默认构造函数来为我们初始化列表。

public class Unit
{
    public string Name { get; set; }

    public List<Group> Contains { get; set; }

    public Unit()
    {
        Contains = new List<Group>();
    }
}

顺便说一句,对于列表来说,这是一个可怕的名字。 通常是一个函数调用,因为它是一个动词。通常最好使用名词来表示集合,例如 .ContainsContainsGroups

public class Unit
{
    public string Name { get; set; }

    public List<Group> Groups { get; set; }

    public Unit()
    {
        Groups = new List<Group>();
    }
}

评论

0赞 thanby 5/2/2014
啊,由于某种原因,我从未想过这种方法,感谢您指出这一点!Contains
0赞 Crono 5/2/2014
@thanby我建议不要让你的列表属性可写。你不太可能想要那样。
0赞 mason 5/2/2014
@Crono 相反,我让它们一直都是可写的。这仅取决于情况以及对象的使用方式。
0赞 Crono 5/2/2014
恕我直言,@mason这些情况应该是边缘的,而不是您的日常用例。我想不出一种设计,我希望对象在具有空集合而不是空集合时采取不同的行动。
1赞 Muhammad Saifullah 5/2/2014 #3

您已初始化 Unit,但 Unit.Contains 未初始化。在将对象添加到“包含”列表之前,必须对其进行初始化。

Unit unit1 = new Unit() { Name = "Unit 1" };
Group group1 = new Group() { Name = "Group 1", Number = 10, Type = basic_1 };
unit1.Contains = new List<Group>();
unit1.Contains.Add(group1);

在 Unit 类构造函数中,您可以初始化 在此处列出代码

public class Unit
{
public string Name { get; set; }
public List<Group> Contains { get; set; }
public Unit()
{
Contains = new List<Group>();
}
}

我更喜欢第二种解决方案,因为它将确保每当初始化 Unit 时,Contains 都会自动初始化。