【问题标题】:Can't add to a list within a class object无法添加到类对象中的列表
【发布时间】:2013-07-27 17:34:44
【问题描述】:

首先,如果这是一个愚蠢的问题,我要道歉。自 VB6 以来没有编程任何东西后,我已经使用 C# 16 个小时了。我只是想拼凑一个供个人使用的小程序,它从旧的访问数据库中读取并在 Excel 中吐出格式化的报告。对于混乱/低​​效的代码,我深表歉意。

概述:我有两种类类型,“区域”和“设备”。每个“区域”中都有一个设备列表。主程序有一个区域列表。每个数据库中都有不同数量的“区域”,每个“区域”都有不同数量的设备分配给它。我需要按顺序解析区域列表和每个区域上的设备。我从结构和数组开始,流行的观点似乎是这两种方法都不好,反正我运气不好,所以我转向列表和类,而且进展顺利。

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

这是我得到的错误:“对象引用未设置为对象的实例。”我收集的意思是对象为空?

以下是相关代码:

设备类:

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

区域类:

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

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

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

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

    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 类构造函数中初始化它,并在添加 Zone 时(这也是它现在设置的)。

我已确认 Zone 对象存在,并且该 Zone 对象中的 Detectors 列表不为空。有点难过,认为我正在做一些我不应该做的事情,只是不知道更好,或者我错过了一些非常明显的事情。

【问题讨论】:

    标签: c# list class population


    【解决方案1】:

    问题出在你的Zone 班级。您需要按如下方式初始化List&lt;Device&gt;

    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&lt;Device&gt; Devices; 时,你实际上并没有创建一个对象。您正在创建一个可以保存指定对象实例的变量。只有当您将变量声明与对象初始化 (= new List&lt;Device&gt;();) 配对时,您才能获得对象的可用实例。

    从更简单的对象角度考虑相同的问题可能会有所帮助:

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

    【讨论】:

    • 感谢您的快速回复。这就是我最初拥有 Zone 类的方式,并且刚刚将其替换为您建议的类,以防万一,它仍然在代码中的同一点给我同样的错误。
    • 听起来您的代码还有其他问题。我发现了最明显不正确的东西,但这并不意味着没有更微妙的东西。我建议发布一个带有更正代码的新问题,包括您收到的异常的确切文本。
    • 再次感谢您的宝贵时间。我了解如何声明它,并且我需要对其进行初始化。在上面的代码中,我尝试初始化它(在尝试在 Zone 类中执行它之后,如您所建议的那样),如下所示: Zones.Find(z => z.ID == dbRow.Address).Devices = new List();这“有效”,因为它得到的结果与在 Zone 类本身中初始化它时得到的结果相同 - 这是对象引用错误。
    • 感谢您的帮助。你是对的 - 这不是区域类的问题,而是其他一些代码的问题。我将代码设置为仅添加非“空白”区域,因为实际上您永远无法将设备分配给“空白”区域。在这种情况下,这是用户(我)错误。在我们的 IDE 中创建我的测试数据库时,我确实将一个设备分配给了一个空白区域。当我的代码找到该设备并尝试将其分配给它的区域时 - 该区域不存在。
    【解决方案2】:

    我认为问题出在您的Zone 班级。

    这是我的 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.Devices = new List<Device>();
    

    现在它可能会起作用......

    【讨论】:

      【解决方案3】:

      您还可以在 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));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-30
        • 2020-06-22
        • 1970-01-01
        • 2016-11-06
        • 1970-01-01
        • 1970-01-01
        • 2013-02-05
        相关资源
        最近更新 更多