C# 中的结构体数组

发布于 2024-11-29 07:30:22 字数 1743 浏览 1 评论 0原文

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

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

I'm trying to get input from user using array of structs and then print it:

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
    }

}
}

Unfortunately after entering all the data I get:

CA4.Program+StudentDetails

CA4.Program+StudentDetails

CA4.Program+StudentDetails

CA4.Program+StudentDetails

CA4.Program+StudentDetails

It doesn't crash, just instead of the data that I entered get the above 5 lines.

I know that the reason why it doesn't work is that I don't use the structs correctly because without them there is no problem.

Can somebody please help me and tell me how to use structs propely in the example above. Thanks

Cheers,

n1te

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等往事风中吹 2024-12-06 07:30:22

这是因为默认情况下 ToString() 返回一个类型名称,您必须自己为 StudentDetails 结构覆盖它:

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

顺便说一句,为什么您要使用 Stuct 和旧数组?考虑使用 class 代替 struct,并使用通用 IListIDictionary 代替数组。
因为传统数组与结构(基本上是值类型)一起引入了装箱(结构 -> 对象),每次将项目添加到数组时都会引入装箱,并在读回它时拆箱(对象 -> 结构)。

This is because by default ToString() returns a Type name, you've to override it yourself for StudentDetails struct:

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

BTW, why you are using stuct and legacy arrays? Consider using class instead struct, and Generic IList<StudentDetails> or IDictionary<int, StudentDetails> instead of array.
Because legacy arrays together with struct (basically value type) introduces a boxing (struct -> object) each time you've adding item to array and unboxing (object -> struct) when reading it back.

晚风撩人 2024-12-06 07:30:22

您对 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);
    }
}

但是,更大的问题是您要通过声明数组 StudentDetails[,] Student = new StudentDetails[5, 1]; 来设置 5 个不同 StudentDetails 结构的属性... code> 并要求用户输入有关数组中不同点的结构的详细信息,即 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();

...

“Then”即可将其写出来:

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

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

希望这会有所帮助。

Your call to Console.WriteLine("{0} ", student[row, column]); is implicitly calling the ToString() method of the StudentDetails struct, which just writes out the name of the struct type by default. Override the ToString() method:

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);
    }
}

However, the larger issue is that you are setting the properties of 5 different StudentDetails structs... by declaring an array StudentDetails[,] student = new StudentDetails[5, 1]; and asking the user to input details about the structs at different points in the array, i.e. student[0, 0] then student[1,0], you aren't making one StudentDetails object and setting properties on it, you created 5 different StudentDetails objects.

Why are you using an array? If you want to the user to fill in a single StudentDetails object, just do

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();

...

Then to write it out:

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

This will use the ToString() method you declared in your StudentDetails struct. (ToString() is called whenever an object needs to be converted to a string, you just don't always have to write it)

Hope this helps.

静赏你的温柔 2024-12-06 07:30:22

其他人已经介绍了 ToString() 的重写,因此我不会重复这些信息。更重要的是,根据您的要求:

有人可以帮助我并告诉我如何在上面的示例中正确使用结构吗?

请参阅MSDN:结构设计

首先,你的结构是可变的。不可变结构并不总是最好的解决方案,但应该考虑...请参阅我关于 Microsoft 使用 Dictionary 类中的结构。也就是说,我会确定基本要求:结构体是否需要可变性?换句话说,在结构体实例化后,学生的姓名、单元号或分数会改变吗?

其次,如果要求有一个 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;
    }
}

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

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++;
}

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

Others have covered the override of ToString(), so I won't rehash that information. More so, to your request:

Can somebody please help me and tell me how to use structs propely in the example above.

See MSDN: Structure Design

First, your struct is mutable. Immutable structs are not always the best solution but should be considered ...see a post I have on Microsoft's use of structs inside the Dictionary class. That said, I would determine the basic requirement: Does the struct require mutability? In other words, will the student's name, unit number, or mark change after struct instantiation?

Second, if the requirement is to have a collection of StudentDetails, an array is fine:

//    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++;
}

Note: exception handling is not considered in this example; e.g., incrementing beyond the bounds of the array.

In the previous example, you could change any of the properties of the StudentDetails struct after instantiation. Structs are made more safe when immutable:

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;
    }
}

This requires a change in how you add the details object to the students array:

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++;
}

Consider the requirements for the struct and design appropriately.

时光磨忆 2024-12-06 07:30:22

您需要适当地打印结构的成员。我建议使用一种方法为给定的结构进行打印,例如

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

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

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

You need to print the members of the struct appropriately. I would suggest a method that does the printing for you given a struct such as

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

Alternatively create a Class (This is C#) and override the ToString() method to return a string with all the member information and you won't need to modify your main code.

Structs are all right to use in C# but in cases where you need data representation rather than just simple data transfer than you should use a class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文