C#中的结构数组

我正在尝试使用结构数组从用户那里获得输入然后打印它:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CA4 { class Program { static void Main(string[] args) { StudentDetails[,] student = new StudentDetails[5, 1]; Console.WriteLine("Please enter the unit code:"); student[0, 0].unitCode = Console.ReadLine(); Console.WriteLine("Please enter the unit number:"); student[1, 0].unitNumber = Console.ReadLine(); Console.WriteLine("Please enter first name:"); student[2, 0].firstName = Console.ReadLine(); Console.WriteLine("Please enter last name:"); student[3, 0].lastName = Console.ReadLine(); Console.WriteLine("Please enter student mark:"); student[4, 0].studentMark = int.Parse(Console.ReadLine()); for (int row = 0; row < 5; row++) { Console.WriteLine(); for (int column = 0; column < 1; column++) Console.WriteLine("{0} ", student[row, column]); } Console.ReadLine(); } public struct StudentDetails { public string unitCode; //eg CSC10208 public string unitNumber; //unique identifier public string firstName; //first name public string lastName;// last or family name public int studentMark; //student mark } } } 

不幸的是,输入所有数据后我得到:

 CA4.Program+StudentDetails CA4.Program+StudentDetails CA4.Program+StudentDetails CA4.Program+StudentDetails CA4.Program+StudentDetails 

它不会崩溃,只是代替我输入的数据获得上述5行。

我知道它不起作用的原因是我没有正确使用结构,因为没有它们没有问题。

有人可以帮助我,告诉我如何在上面的例子中使用结构。 谢谢

干杯,

n1te

您对Console.WriteLine("{0} ", student[row, column]);调用Console.WriteLine("{0} ", student[row, column]); 隐式调用StudentDetails结构的ToString()方法,默认情况下只写出结构类型的名称。 重写ToString()方法:

 public struct StudentDetails { public string unitCode; //eg CSC10208 public string unitNumber; //unique identifier public string firstName; //first name public string lastName;// last or family name public int studentMark; //student mark public override string ToString() { return string.Format("{0},{1},{2},{3},{4}", unitCode, unitNumber,firstName,lastName,studentMark); } } 

但是,更大的问题是你要设置5个不同的StudentDetails结构的属性……通过声明一个数组StudentDetails[,] student = new StudentDetails[5, 1]; 并要求用户输入有关数组中不同点的结构的详细信息,即student[0, 0]然后student[1,0] ,你没有制作一个StudentDetails对象并在其上设置属性,你创建了5个不同的 StudentDetails对象。

你为什么要使用arrays? 如果您希望用户填写单个StudentDetails对象,请执行此操作

 StudentDetails student = new StudentDetails(); Console.WriteLine("Please enter the unit code:"); student.unitCode = Console.ReadLine(); Console.WriteLine("Please enter the unit number:"); student.unitNumber = Console.ReadLine(); ... 

然后把它写出来:

 Console.WriteLine("{0}", student); 

这将使用您在StudentDetails结构中声明的ToString()方法。 (只要需要将对象转换为字符串,就会调用ToString(),您不必总是编写它)

希望这可以帮助。

这是因为默认情况下ToString()返回一个Type名称,你要自己为StudentDetails结构覆盖它:

 public struct StudentDetails { public override void ToString() { return String.Format( CultureInfo.CurrentCulture, "FirstName: {0}; LastName: {1} ... ", this.FirstName, this.LastName); } } 

顺便说一句,你为什么使用stuct和传统arrays? 考虑使用class而不是struct ,以及Generic IListIDictionary而不是数组。 因为遗留数组与struct(基本上是值类型)一起引入了一个装箱(struct – > object),每次你将数据添加到数组并在读取时取消装箱(object – > struct)。

其他人已经覆盖了ToString()的覆盖,所以我不会重复这些信息。 更重要的是,根据您的要求:

有人可以帮助我,告诉我如何在上面的例子中使用结构。

请参阅MSDN:结构设计

首先,你的结构是可变的。 不可变的结构并不总是最好的解决方案,但应该考虑…看看我对微软在Dictionary类中使用结构的post。 也就是说,我会确定基本要求: 结构是否需要可变性? 换句话说,结构实例化后,学生的姓名,单元号或标记是否会发生变化?

其次,如果要求是拥有StudentDetails的集合,则数组是正常的:

 // declare students collection StudentDetail[] students = new StudentDetail[5]; // declare an array indexer int indexer = 0; static void Main(string[] args) { Console.WriteLine("Please enter the unit code:"); string unitCode = Console.ReadLine(); Console.WriteLine("Please enter the unit number:"); string unitNumber = Console.ReadLine(); /* get the rest of your inputs */ AddStudentDetails(unitCode, unitNumber, firstName, lastName, studentMark); } // demonstrate auto-magically instantiated, mutable struct void AddStudentDetails(string unitCode, string unitNumber, string firstName, string lastName, int studentMark) { students[indexer].unitCode = unitCode; students[indexer].unitNumber = unitNumber; students[indexer].firstName = firstName; students[indexer].lastName = lastName; students[indexer].studentMark = studentMark; // increment your indexer indexer++; } 

注意:此示例中不考虑exception处理; 例如,递增超出数组的范围。

在前面的示例中,您可以在实例化后更改StudentDetails结构的任何属性。 不可变时,结构更安全

 public struct StudentDetails { public readonly string unitCode; //eg CSC10208 public readonly string unitNumber; //unique identifier public readonly string firstName; //first name public readonly string lastName;// last or family name public readonly int studentMark; //student mark // use a public constructor to assign the values: required by 'readonly' field modifier public StudentDetails(string UnitCode, string UnitNumber, string FirstName, string LastName, int StudentMark) { this.unitCode = UnitCode; this.unitNumber = UnitNumber; this.firstName = FirstName; this.lastName = LastName; this.studentMark = StudentMark; } } 

这需要更改将详细信息对象添加到students数组的方式:

 void AddStudentDetails(string unitCode, string unitNumber, string firstName, string lastName, int studentMark) { students[indexer] = new StudentDetails(unitCode, unitNumber, firstName, lastName, studentMark); // increment your indexer indexer++; } 

适当考虑结构和设计的要求。

您需要适当地打印结构的成员。 我会建议一个方法,给你一个像你这样的结构打印

 public void PrintStruct(StudentDetails stDetails) { Console.WriteLine(stDetails.firstName); Console.WriteLine(stDetails.lastName); .... etc } 

或者创建一个Class(这是C#)并覆盖ToString()方法以返回包含所有成员信息的字符串,您不需要修改主代码。

结构可以在C#中使用,但是在需要数据表示而不仅仅是简单数据传输的情况下,您应该使用类。