如何在 C# 中正确地将一个数组添加到另一个数组?
How to properly add an array to another array in C#?
我正在 Windows 的学校项目中进行动物登记。我有一个 Animal class,其中使用属性 Id、Name、Age、Gender 和 Friendly 创建动物对象。我还有一个处理列表的 AnimalManager class,通过它可以添加更多动物。在运行时,当用信息填写适当的框并按下添加动物按钮时,信息应该添加到列表视图中的一行(任务的重要部分。当我可以将它显示在列表框)。
当我将信息打印到列表框时,我只是通过 public string AnimalInformation()
从 Animal class 向 AnimalManager 发送了一个包含适当信息的字符串,AnimalManager 编译了一个数组并将其发送到 Form1被打印。因为我想在列表视图中显示它,我想我应该将 AnimalInformation()
变成一个数组,这样我在通过 AnimalManager 后得到一个二维数组,就像打印时显示的一样。但是,当 运行 程序并尝试添加动物时,我在我的 AnimalManager 中收到异常消息 System.NullReferenceException: 'Object reference not set to an instance of an object.'。
这是Animal中的方法class:
public string[] AnimalInformation()
{
string[] strOut = { id, name, age.ToString(), gender.ToString(), FriendlyStr()};
return strOut;
}
这是AnimalManager中的方法class:
public string[][] GetAnimalInfoArray()
{
string[][] animals = new string[animalList.Count][];
for(int i = 0; i < animalList.Count; i++)
{
Animal animal = animalList[i];
for(int j = 0; j < animal.CountAnimalInfo(); j++)
{
string[] info = animal.AnimalInformation();
animals[i][j] = info[j];
}//here comes the exception
}
return animals;
}
并且由于我不太熟悉 listview(阅读:一点也不熟悉),这是我编写的循环,用于在我的 UpdateGUI()
方法中将其全部打印到 listview 中,以防这是导致的原因麻烦:
if (manager.Count() > 0)
{
foreach(string[] row in manager.GetAnimalInfoArray())
{
foreach(string item in row)
lvwAnimals.Items.Add(item);
}
}
我已经在这里待了几个小时了,不知道发生了什么。我走在正确的轨道上吗?我必须完全返工吗?在大括号后收到错误消息我做错了什么?
我知道这不会直接回答,JeremyLakeMan 评论您现在遇到问题的原因。但这是我会做的
给定一个名为 animalList 的 Animals IEnumerable(您已经拥有)
假设动物看起来像这样
public class Animal{
public string ID;
public String Name;
public int Age;
}
现在
foreach(var animal in animals)
{
lvwAnimals.Items.Add(animal.ID);
lvwAnimals.Items.Add(animal.Name);
lvwAnimals.Items.Add(animal.Age.ToString());
}
就是这样,不需要整个 GetAnimalInfoArray
第一个问题是您正在创建一个数组数组,但没有在数组中分配数组...这有点令人困惑,但这是一行:
string[][] animals = new string[animalList.Count][];
animals
是string[]
的数组。此时,animals
数组中的每个元素都是null,不是数组。您遇到问题的地方是:
animals[i][j] = info[j];
此时animals[i]
未初始化(null
),所以没有数组供你用j
索引。
这个问题有多种解决方法,但最直接的方法是简单地将调用AnimalInformation
的结果赋值给数组槽并完成:
public string[][] GetAnimalInfoArray()
{
string[][] animals = new string[animalList.Count][];
for(int i = 0; i < animalList.Count; i++)
animals[i] = animalList[i].AnimalInformation();
return animals;
}
如果您可以使用 LINQ,那么还有一个更简单的选项:ToArray()
。
public string[][] GetAnimalInfoArray()
=> animalList.Select(a => a.AnimalInformation()).ToArray();
关于其余代码的一些注释...
您的内循环为信息数组中的每个项目调用 CountAnimalInfo()
和 AnimalInformation()
。那是你调用这两种方法的 5 次,每次你至少创建一个数组(我假设你不是从 CountAnimalInfo()
内部调用 AnimalInformation()
,如果你是那么那是两个每个项目的数组)。如果您必须循环,最好只调用一次并使用结果数组进行循环。
for (int i = 0; i < animalList.Count; i++)
{
var info = animalList[i].AnimalInformation();
animals[i] = new string[info.Length];
for (int j = 0; j < info.Length; j++)
animals[i][j] = info[j];
}
您正在将看似显示代码的内容分散到多个方法和 classes 中。虽然有时能够覆盖 sub-classes 中的内容很有用,但通常(至少以我的经验)将显示代码放在一个地方是更可取的:单个方法或紧密耦合的方法组单身 class。 Animal
不需要知道它是如何显示的,它只需要呈现其他代码可以使用的属性。您的 AnimalManager
class 可能也不需要充当您的显示代码的 go-between,这取决于显示代码来确定应该如何显示。试试这个:
foreach (var animal in manager.animalList)
{
lvwAnimals.Items.Add(animal.id);
lvwAnimals.Items.Add(animal.name);
lvwAnimals.Items.Add(animal.age.ToString());
lvwAnimals.Items.Add(animal.gender.ToString());
lvwAnimals.Items.Add(animal.FriendlyStr());
}
这样您就将 'display' 问题与 non-display class 问题分开了,让他们更专注于自己的工作。还有额外的好处,以后调试的代码行少了很多。
我正在 Windows 的学校项目中进行动物登记。我有一个 Animal class,其中使用属性 Id、Name、Age、Gender 和 Friendly 创建动物对象。我还有一个处理列表的 AnimalManager class,通过它可以添加更多动物。在运行时,当用信息填写适当的框并按下添加动物按钮时,信息应该添加到列表视图中的一行(任务的重要部分。当我可以将它显示在列表框)。
当我将信息打印到列表框时,我只是通过 public string AnimalInformation()
从 Animal class 向 AnimalManager 发送了一个包含适当信息的字符串,AnimalManager 编译了一个数组并将其发送到 Form1被打印。因为我想在列表视图中显示它,我想我应该将 AnimalInformation()
变成一个数组,这样我在通过 AnimalManager 后得到一个二维数组,就像打印时显示的一样。但是,当 运行 程序并尝试添加动物时,我在我的 AnimalManager 中收到异常消息 System.NullReferenceException: 'Object reference not set to an instance of an object.'。
这是Animal中的方法class:
public string[] AnimalInformation()
{
string[] strOut = { id, name, age.ToString(), gender.ToString(), FriendlyStr()};
return strOut;
}
这是AnimalManager中的方法class:
public string[][] GetAnimalInfoArray()
{
string[][] animals = new string[animalList.Count][];
for(int i = 0; i < animalList.Count; i++)
{
Animal animal = animalList[i];
for(int j = 0; j < animal.CountAnimalInfo(); j++)
{
string[] info = animal.AnimalInformation();
animals[i][j] = info[j];
}//here comes the exception
}
return animals;
}
并且由于我不太熟悉 listview(阅读:一点也不熟悉),这是我编写的循环,用于在我的 UpdateGUI()
方法中将其全部打印到 listview 中,以防这是导致的原因麻烦:
if (manager.Count() > 0)
{
foreach(string[] row in manager.GetAnimalInfoArray())
{
foreach(string item in row)
lvwAnimals.Items.Add(item);
}
}
我已经在这里待了几个小时了,不知道发生了什么。我走在正确的轨道上吗?我必须完全返工吗?在大括号后收到错误消息我做错了什么?
我知道这不会直接回答,JeremyLakeMan 评论您现在遇到问题的原因。但这是我会做的
给定一个名为 animalList 的 Animals IEnumerable(您已经拥有)
假设动物看起来像这样
public class Animal{
public string ID;
public String Name;
public int Age;
}
现在
foreach(var animal in animals)
{
lvwAnimals.Items.Add(animal.ID);
lvwAnimals.Items.Add(animal.Name);
lvwAnimals.Items.Add(animal.Age.ToString());
}
就是这样,不需要整个 GetAnimalInfoArray
第一个问题是您正在创建一个数组数组,但没有在数组中分配数组...这有点令人困惑,但这是一行:
string[][] animals = new string[animalList.Count][];
animals
是string[]
的数组。此时,animals
数组中的每个元素都是null,不是数组。您遇到问题的地方是:
animals[i][j] = info[j];
此时animals[i]
未初始化(null
),所以没有数组供你用j
索引。
这个问题有多种解决方法,但最直接的方法是简单地将调用AnimalInformation
的结果赋值给数组槽并完成:
public string[][] GetAnimalInfoArray()
{
string[][] animals = new string[animalList.Count][];
for(int i = 0; i < animalList.Count; i++)
animals[i] = animalList[i].AnimalInformation();
return animals;
}
如果您可以使用 LINQ,那么还有一个更简单的选项:ToArray()
。
public string[][] GetAnimalInfoArray()
=> animalList.Select(a => a.AnimalInformation()).ToArray();
关于其余代码的一些注释...
您的内循环为信息数组中的每个项目调用 CountAnimalInfo()
和 AnimalInformation()
。那是你调用这两种方法的 5 次,每次你至少创建一个数组(我假设你不是从 CountAnimalInfo()
内部调用 AnimalInformation()
,如果你是那么那是两个每个项目的数组)。如果您必须循环,最好只调用一次并使用结果数组进行循环。
for (int i = 0; i < animalList.Count; i++)
{
var info = animalList[i].AnimalInformation();
animals[i] = new string[info.Length];
for (int j = 0; j < info.Length; j++)
animals[i][j] = info[j];
}
您正在将看似显示代码的内容分散到多个方法和 classes 中。虽然有时能够覆盖 sub-classes 中的内容很有用,但通常(至少以我的经验)将显示代码放在一个地方是更可取的:单个方法或紧密耦合的方法组单身 class。 Animal
不需要知道它是如何显示的,它只需要呈现其他代码可以使用的属性。您的 AnimalManager
class 可能也不需要充当您的显示代码的 go-between,这取决于显示代码来确定应该如何显示。试试这个:
foreach (var animal in manager.animalList)
{
lvwAnimals.Items.Add(animal.id);
lvwAnimals.Items.Add(animal.name);
lvwAnimals.Items.Add(animal.age.ToString());
lvwAnimals.Items.Add(animal.gender.ToString());
lvwAnimals.Items.Add(animal.FriendlyStr());
}
这样您就将 'display' 问题与 non-display class 问题分开了,让他们更专注于自己的工作。还有额外的好处,以后调试的代码行少了很多。