可以';t添加到类对象内的列表中
本文关键字:对象 列表 添加 可以 | 更新日期: 2023-09-27 18:25:07
首先,如果这是一个愚蠢的问题,我要道歉。自从VB6之后,我一直没有编程过任何东西,现在我已经使用C#16个小时了。我只是想破解一个个人使用的小程序,它从旧的访问数据库中读取数据,并在Excel中输出格式化的报告。我为混乱/低效的代码道歉。
概述:我有两种类类型,"区域"answers"设备"。每个"区域"都有一个设备列表。主程序有一个区域列表。每个数据库中都有不同数量的"区域",每个"区域"都分配了不同数量的设备。我需要依次解析区域列表和每个区域上的设备。我从结构和数组开始,流行的观点似乎是这两种方法都不好,而且我运气不好,所以我转向了列表和类,进展顺利。
我可以从数据库中提取所有"区域",将它们添加到列表中,为它们分配标签和ID。问题是,当我从数据库中读取"设备"时,我无法将它们添加到区域内的列表中。
这是我得到的错误:"对象引用没有设置为对象的实例。"我收集到的意思是对象为null?
这是相关代码:
设备类别:
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对象中的探测器列表不是空的。有点困惑,觉得我在做一些我不应该做的事情,只是不知道得更好,或者我错过了一些非常明显的事情。
问题出在Zone
类中。您需要初始化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));
}
}
原因是当您编写public List<Device> Devices;
时,实际上并不是在创建一个对象。您正在创建一个变量,该变量可以容纳指定对象的实例。只有当您将变量声明与对象初始化(= new List<Device>();
)配对时,您才能获得对象的可用实例。
从一个更简单的对象的角度思考同样的问题可能会有所帮助:
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
类版本:
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>();
现在它可能会起作用。。。
您还可以在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));
}
}