c#中的结构体数组
本文关键字:数组 结构体 | 更新日期: 2023-09-27 18:05:22
我试图从用户使用数组的结构,然后打印它的输入:
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
这是因为默认情况下ToString()
返回一个类型名称,您必须自己为StudentDetails
struct重写它:
public struct StudentDetails
{
public override void ToString()
{
return String.Format(
CultureInfo.CurrentCulture,
"FirstName: {0}; LastName: {1} ... ",
this.FirstName,
this.LastName);
}
}
顺便说一句,为什么你要使用struct和遗留数组?考虑使用class
代替struct
,使用Generic IList<StudentDetails>
或IDictionary<int, StudentDetails>
代替array。因为遗留数组与struct(基本上是值类型)一起在每次向数组中添加项和在读取它时拆箱(object -> struct)时引入了装箱(struct ->对象)。
对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对象。
为什么要使用数组?如果您想让用户填写单个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()
的覆盖,所以我不会重复该信息。更重要的是,根据您的要求:
谁能告诉我如何在上面的例子中正确地使用结构体
参见MSDN:结构设计
首先,你的结构是可变的。不可变结构并不总是最好的解决方案,但应该考虑…看看我的一篇关于微软在字典类中使用结构体的文章。也就是说,我将确定基本需求:结构是否需要可变性?换句话说,在结构实例化之后,学生的名字、单元号或标记会改变吗?
第二,如果要求有一个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++;
}
注意:本例中不考虑异常处理;例如,超出数组的边界自增。
在前面的示例中,您可以在实例化之后更改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;
}
}
这需要更改将details对象添加到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
}
或者创建一个类(这是c#)并覆盖ToString()方法来返回一个包含所有成员信息的字符串,您不需要修改主代码。
结构在c#中是可以使用的,但是当你需要数据表示而不仅仅是简单的数据传输时,你应该使用类。