简体   繁体   English

无法添加到类对象中的列表

[英]Can't add to a list within a class object

First, I'm going to apologize if this is a stupid question. 首先,如果这是一个愚蠢的问题,我会道歉。 I've been using C# for 16 hours after having not programmed anything since VB6. 自VB6以来我没有编程任何东西后,我一直在使用C#16个小时。 I'm just trying to hack together a small program for personal use that reads from an old access database and spits out a formatted report in Excel. 我只是试图破解一个小程序供个人使用,从旧的访问数据库读取并在Excel中吐出格式化的报告。 I apologize for the messy/inefficient code. 我为凌乱/低效的代码道歉。

Overview: I have two class types, "Zone" and "Device". 概述:我有两种类型,“区域”和“设备”。 Each "Zone" has a List of Devices in it. 每个“区域”都有一个设备列表。 The main program has a List of Zones. 主程序有一个区域列表。 Each database has a varying number of "zones" in it, and each "zone" has a varying number of devices assigned to it. 每个数据库中都有不同数量的“区域”,每个“区域”具有分配给它的不同数量的设备。 I need to parse, sequentially, the zone list and the devices on each zone. 我需要按顺序解析区域列表和每个区域上的设备。 I started with structs and arrays and popular opinion seems to be that those are both bad ways to do it, and I wasn't having much luck anyway, so I moved to lists and classes, and it was going well. 我从结构和数组开始,流行的观点似乎是那些都是不好的方法,而且我反正运气不好,所以我搬到了列表和课程,而且进展顺利。

I can pull all the "zones" from the database, add them to the list, assign them their labels and IDs. 我可以从数据库中提取所有“区域”,将它们添加到列表中,为它们分配标签和ID。 The problem is when I go to read the "devices" from the database, I can't add them to the list within the Zone. 问题是当我从数据库中读取“设备”时,我无法将它们添加到区域内的列表中。

This is the error I get: "Object reference not set to an instance of an object." 这是我得到的错误:“对象引用未设置为对象的实例。” Which I gather means the object is null? 我收集哪个意味着该对象为空?

Here's the relevant code: 这是相关的代码:

Device Class: 设备类别:

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

Zone Class: 区域类别:

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

Initializing and populating Zone List (on button click) (completes successfully) 初始化和填充区域列表(按钮单击)(成功完成)

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

Adding Devices to their respective Zones: 将设备添加到各自的区域:

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

            }

I've gone through and found out exactly where it fails, and it's the last line where it tries to add the device. 我已经完成并确切地知道它失败了,这是它尝试添加设备的最后一行。 Searching here and on google has lead me to believe that I need to initialize the object list... which I believe I've done? 在这里和谷歌搜索让我相信我需要初始化对象列表...我相信我已经完成了? I've tried initializing it within the Zone class constructor, and when the Zone is added (which is what it's set too now). 我已经尝试在Zone类构造函数中初始化它,并且在添加区域时(这也是现在设置的)。

I've confirmed that the Zone object exists, and that the Detectors list within that Zone object isn't null. 我已确认Zone对象存在,并且该Zone对象中的Detectors列表不为null。 Kinda stumped, figure I'm doing something that I shouldn't be doing and just don't know better, or I'm missing something really obvious. 有点难过,我想我正在做一些我不应该做的事情,只是不知道更好,或者我错过了一些非常明显的事情。

The problem is in your Zone class. 问题出在您的Zone类中。 You need to initialize the List<Device> as follows. 您需要按如下方式初始化List<Device>

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

The reason is that when you write public List<Device> Devices; 原因是当你写public List<Device> Devices; , you're not actually creating an object. ,你实际上并没有创建一个对象。 You're creating a variable that can hold an instance of the specified object. 您正在创建一个可以保存指定对象实例的变量。 It's only when you pair the variable declaration up with object initialization ( = new List<Device>(); ) that you get a usable instance of the object. 只有当您将变量声明与对象初始化( = new List<Device>(); )配对时,您才能获得该对象的可用实例。

Thinking of the same issue in terms of a simpler object may help: 从更简单的对象来考虑同样的问题可能会有所帮助:

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
    }

}

I think the problem is in your Zone class. 我认为问题出在你的Zone类中。

Here is my version of your Zone class: 这是我的Zone类的版本:

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

This is an only change that I made to your class; 这是我对你们班级的唯一改变;

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

Now it might work... 现在它可能会起作用......

You can also initialize the list inside a getter 您还可以在getter中初始化列表

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM