Array of structs in C#
Solution 1
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.
Solution 2
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.
Solution 3
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.
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.
Solution 4
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.
n1te
49206c757620636f64696e672e200d0a0d0a453a206e3174656c6565745b61745 d5b656d61696c2e73797374656d2e637265617465642e62792e676f6f676c655d
Updated on June 27, 2022Comments
-
n1te almost 2 years
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
-
siride over 12 yearsMinor nitpick: string builder is a lot of work for no gain. Just use concatenation or a single
string.Format()
. -
n1te over 12 yearsFirst of all thanks to everybody for prompt responses To be honest I dont have to use an array here but the next assignment is similar and I'm required to use arrays there, so I wanted to practice. In the next assignment I have to accept the data as: week number, home team name, away team name, win (1 or 0) _italic_Your program must use an array/s of structures to store the data in memory, i.e. your program must read the data from the file/s into memory as an array of structs and manipulate the data in the array. and there will be 5 weeks total and 80 matches (there is 16 teams)
-
n1te over 12 yearsThat's why I figured that I would give it a go here so it's easier in the next assignment. @Nick Bradley
-
Nick B over 12 yearsThat's fine, as long as you understand that, in the original code you posted, you aren't filling in a StudentDetails struct - you are filling in five different ones, but you are only filling in the unitCode in the 1st one (At [0,0]) unitNumber in the 2nd one ([1,0]) firstName in the 3rd.. etc. You aren't completely filling any of the StudentDetails structs you make.
-
IAbstract over 12 years"but in cases where you need data representation rather than just simple data transfer than you should use a class." ...not always true. ;)
-
IAbstract over 12 years@n1te: keep to the requirements of your current assignment. While it shows desire to learn, not following the requirements could negatively reflect on the grade you receive. ;)
-
Olivier Jacot-Descombes over 12 yearsI agree with Nick. What you probably need is a 1-dimensional array of StudenDetails.
student[0].firstName = "Mickey"; student[0].lastName = "Mouse";
-
n1te over 12 yearsThanks a lot for the answer, it will make my life a lot easier in the next assignment. Btw. Good point with keeping the requirements, will do :)