关于c#:无法添加到类对象中的列表

Can't add to a list within a class object

首先,如果这是一个愚蠢的问题,我会道歉的。自从vb6以来,我一直在使用c_16个小时,没有编程任何东西。我只是想破解一个个人使用的小程序,它从旧的Access数据库中读取数据,并在Excel中输出格式化的报告。我为混乱/低效的代码道歉。

概述:我有两个类类型,"区域"和"设备"。每个"区域"中都有一个设备列表。主程序有一个区域列表。每个数据库中都有不同数量的"区域",并且每个"区域"都有不同数量的设备分配给它。我需要按顺序分析区域列表和每个区域上的设备。我从结构和数组开始,人们普遍认为这两种方法都是不好的,而且我也没有太多运气,所以我搬到了列表和类,一切都很顺利。

我可以从数据库中提取所有"区域",将它们添加到列表中,为它们分配标签和ID。问题是,当我从数据库中读取"设备"时,无法将它们添加到区域内的列表中。

这是我得到的错误:"对象引用没有设置为对象的实例。"我收集到的信息表示对象为空?

相关代码如下:

设备类别:

1
2
3
4
5
6
7
8
9
10
11
12
    public class Device
    {
        public string Label;
        public string Address;
        public string Type;
        public Device(string Label, string Address, string Type)
        {
            this.Address = Address;
            this.Label = Label;
            this.Type = Type;
        }
    }

区域类别:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public class Zone
    {
        public string Label;
        public short ID;
        public List<Device> Devices;

        public Zone(string Label, short ID) {
            this.Label = Label;
            this.ID = ID;
            // ADDED AS PER SUGGESTIONS BELOW
            this.Devices = new List<Device>();
        }

        // Added this to see if it would work, it would not.
        public void AddDevice(string Label, string Address, string Type) {
            Devices.Add(new Device(Label, Address, Type));
        }            
    }

初始化和填充区域列表(单击按钮)(成功完成)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    List<Classes.Zone> Zones = new List<Classes.Zone>();
    dbZoneReader = myZoneSelect.ExecuteReader();

            while (dbZoneReader.Read())
            {
                Classes.dbItem dbRow = new Classes.dbItem();
                dbRow.Address = Convert.ToInt16(dbZoneReader["DeviceAddress"].ToString());
                dbRow.DeviceType = Convert.ToInt16(dbZoneReader["DeviceType"].ToString());
                dbRow.Label = dbZoneReader["DeviceLabel"].ToString();

                if (dbRow.Label !="" && dbRow.Address > 0)
                {
                    Zones.Add(new Classes.Zone(dbRow.Label,dbRow.Address));                        
                }
            }

将设备添加到各自的区域:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    while (dbReader.Read()) {  
                Classes.dbItem dbRow = new Classes.dbItem();                    
                string tempZones;

                // Acquire/convert device information
                dbRow.Node = Convert.ToInt16(dbReader["NodeAddress"].ToString());                                    
                dbRow.Loop = Convert.ToInt16(dbReader["LoopSelection"].ToString());                                  
                dbRow.Address = Convert.ToInt16(dbReader["DeviceAddress"].ToString());                                
                dbRow.TypeID = Convert.ToInt16(dbReader["TypeID"].ToString());                                    
                dbRow.FlashScanID = Convert.ToInt16(dbReader["FlashScanID"].ToString());
                dbRow.DeviceType = Convert.ToInt16(dbReader["DeviceType"].ToString());
                dbRow.Label = dbReader["DeviceLabel"].ToString();

                // Find"proper" zone ID (some zones have multiple IDs, only one is relevant)
                tempZones = dbReader["DevicePointMappingList"].ToString();
                tempZones = tempZones.Replace("Z","");
                var elements = tempZones.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
                if (elements.Length >= 2) {
                    ZoneCheck z = new ZoneCheck();
                    foreach (string items in elements) { if (z.Check(items))  { dbRow.Zone = Convert.ToInt16(items); } }
                } else {
                    if (elements.Length == 1) { dbRow.Zone = Convert.ToInt16(elements[0]); }
                    else { dbRow.Zone = 0; }
                }

                // Only add devices that aren't assigned to zone 0, which is non-existent
                if (dbRow.Zone > 0)  {  
                    // Add new device to zone's device list [THIS IS WHERE IT FAILS]
                    Zones.Find(z => z.ID == dbRow.Zone).Devices.Add(new Classes.Device("Test","test","Test"));                                                    
                }

            }

我已经检查过了,发现了它到底在哪里失败,这是它试图添加设备的最后一行。搜索这里和谷歌,让我相信我需要初始化对象列表…我相信我已经做到了?我尝试在区域类构造函数中初始化它,并且在添加区域时(这也是它现在设置的)。

我已经确认区域对象存在,并且该区域对象中的检测器列表不是空的。有点困惑,觉得我在做一些我不该做的事情,只是不知道更好,或者我错过了一些非常明显的事情。


问题出在你的Zone类中。您需要如下初始化List

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Zone
{
    public string Label;
    public short ID;
    public List<Device> Devices;

    public Zone(string Label, short ID) {
        this.Label = Label;
        this.ID = ID;
        this.Devices = new List<Device>();
    }

    // Added this to see if it would work, it would not.
    public void AddDevice(string Label, string Address, string Type) {
        Devices.Add(new Device(Label, Address, Type));
    }            
}

原因是,当您编写public List Devices;时,实际上并没有创建对象。您正在创建一个可以保存指定对象实例的变量。只有当您将变量声明与对象初始化(= new List();配对)时,才能获得对象的可用实例。

用一个简单的对象来思考同一个问题可能有助于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Foo
{
    public string bar; // bar isn't an actual instance of an object, it's just a spot that can hold a string

    public void ManipulateBarWithRuntimeError()
    {
        bar.Substring(0, 1); //"bar" isn't actually set to anything, so how can we take a substring of it? This is going to fail at runtime.
    }

    public void ManipulateBarWithoutRuntimeError()
    {
        bar ="Hello, world!";
        bar.Substring(0, 1); // bar is actually set to a string object containing some text, so now the Substring method will succeed
    }

}


还可以在getter中初始化列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Zone
{
    public string Label;
    public short ID;
    private  List<Device> _devices;

    public List<Device> Devices
    {
        get
        {
            return this._devices ?? (this._devices = new List<Device>());
        }
    }


    public Zone(string Label, short ID)
    {
        this.Label = Label;
        this.ID = ID;
    }

    // Added this to see if it would work, it would not.
    public void AddDevice(string Label, string Address, string Type)
    {
        Devices.Add(new Device(Label, Address, Type));
    }
}


我认为问题出在你的Zone班。

这是我对您的Zone类的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Zone
{
    public string Label;
    public short ID;
    public List<Device> Devices;

    public Zone(string Label, short ID) {
        this.Label = Label;
        this.ID = ID;
        this.Devices = new List<Device>();
    }

    // Added this to see if it would work, it would not.
    public void AddDevice(string Label, string Address, string Type) {
        Devices.Add(new Device(Label, Address, Type));
    }            
}

这是我对你们班唯一的改变;

1
this.Devices = new List<Device>();

现在它可能工作了…