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 IList
或IDictionary
而不是数组。 因为遗留数组与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#中使用,但是在需要数据表示而不仅仅是简单数据传输的情况下,您应该使用类。