1

Trying to display the names and student ID with a foreach loop at the end of the program, but instead of listing the names it just gives me the output "Assignment_8.Student". How exactly would I display the names and ID's instead of that directory its giving me?

using System;
using System.Collections.Generic;

namespace Assignment_8
{
class Program
{
    static void Main(string[] args)
    {

         List<Student> myList = new List<Student>();

        Student s1 = new Student();
        s1.FirstName = "John";
        s1.LastName = "Smith";
        s1.StudentID = 2560;
        myList.Add(s1);

        Student s2 = new Student("Peter");
        myList.Add(s2);


        Student s3 = new Student("Morgan", "Simmons");
        myList.Add(s3);

        Student s4 = new Student("James", "Walters");
        myList.Add(s4);

        Student s5 = new Student("Linda", "Scott", 1005);
        myList.Add(s5);


        Console.WriteLine();

        Console.WriteLine("Total students: {0}", Student.Count);

        foreach (var item in myList)
        {
            Console.WriteLine("Student: {0}", item);
        }
       
        
    }
}
}

Here is the Class:

using System;
using System.Collections.Generic;
using System.Text;

namespace Assignment_8
{
class Student
{
    public static int Count { get; private set; }
    private static readonly Random rnd = new Random();

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int StudentID { get; set; }
    

    public Student(string first, string last, int id)
    {
        FirstName = first;
        LastName = last;
        StudentID = id;
        ++Count;
        Console.WriteLine("Student Name: {0} {1}, Student ID: {2}",
            FirstName, LastName, StudentID );
    }

    public Student(string first ="", string last ="")
    {
        FirstName = first;
        LastName = last;
        ++Count;
        Console.WriteLine("Student Name: {0} {1}, Student ID: {2}",
           FirstName, LastName, rnd.Next(1000, 9999) );
    }

}
}

Here is the Output of the program:

Student Name:  , Student ID: 4101
Student Name: Peter , Student ID: 9074
Student Name: Morgan Simmons, Student ID: 2328
Student Name: James Walters, Student ID: 5481
Student Name: Linda Scott, Student ID: 1005

Total students: 5
Student: Assignment_8.Student
Student: Assignment_8.Student
Student: Assignment_8.Student
Student: Assignment_8.Student
Student: Assignment_8.Student

3 Answers 3

2

You need either to use the same approach as you do in constructors:

    foreach (var item in myList)
    {
        Console.WriteLine("Student: {0} {1} {2}", item.StudentID, item.FirstName, item.LastName);
    }

Or to override ToString (otherwise class name will be used to convert class instance to string):

class Student
{
    public override string ToString()
    {
        return string.Format("Student: {0} {1} {2}", StudentID, FirstName, LastName);
    }
}

And usage in you loop:

Console.WriteLine(item);

Also since C# 6 there you can beautify it with string interpolation:

    public override string ToString()
    {
        return $"Student: {StudentID} {FirstName} {LastName}";
    }
Sign up to request clarification or add additional context in comments.

5 Comments

The for each loop works untill it gets to the random student id part. How would I go about it outputting the StudentID's that are set and the ones that are Random as well? I also have to use the foreach loop for this, thanks in advance!
@WilliamDaly you just outputing rnd.Next(1000, 9999) to Console, and not assigning it to StudentID. Also you constructor can invoke another.
How would I go about assigning the rnd.next to the studentID, thats the part that im currently stuck on.
@WilliamDaly the same as you do with non-random id.
Ok I finally got it, I appreciate the help Guru!
1

Simply update the foreach loop as:

Console.WriteLine("Student: {0}, {1}", item.FirstName, item.StudentID);

Comments

1

On this line here:

Console.WriteLine("Student: {0}", item);

item is an object of type Student. Because Microsoft never wrote a WriteLine(string, Student) method that knows specifically how to print out one of your Students with its name and everything, the form of WriteLine that ends up getting used is WriteLine(string, object).

This form of WriteLine will use the first string as a format spec to create a custom string using the other objects passed in in plae of the numbered placeholders in the string. Because it needs the objects to be a string, it simply calls the .ToString() method on whatever thing is passed into it as the object argument, in this case a Student, when it is building the string to output from the format string "Student: {0}".

Because your Student doesn't have a specific version of the ToString() method, it uses the default one on the base object, from which Student is derived (everything inherits from object if it doesn't inherit from something more specific)

The ToString() method on object is very primitive: it merely returns the name of the kind of object it is, in this case a Assignment_8.Student

The end result is that WriteLine(string, object) is processing the "Student: {0}", string, it finds placeholder {0}, it goes to the 0th argument (the Student item), calls ToString() on it, gets "Assignment_8.Student" back, pops it in the string "Student: {0}" in place of the {0} and then finishes its work


To alter things you either need to :

  • Use a different flavor of WriteLine, such as WriteLine(string), by making your string first, and passing the string you made into it:
WriteLine(item.Firstname + " " + item.LastName) 
WriteLine($"{item.Firstname} {item.LastName}")

In this case it is the class that calls WriteLine that gets to decide how a student is to be displayed

  • Use this flavor of WriteLine that accepts a format and a bunch of parameter objects but give actual strings to the parameters: WriteLine("Student FN:{0}, LN:{1}", item.FirstName, item.LastName) - item.FirstName and item.LastName are actually strings that are part of the Student, rather than being the whole Student. Even though these strings will also be passed in as objects, they're still strings at the core of their being, and calling .ToString on a string, returns the string itself, so everything works out
  • Create a version of the ToString() method in your Student class that returns a formatted representation of the student as a string. With this way, yourStudent goes in, has ToString() called on it, gets its chance to shine and return a pretty version of itself, and the result is inserted into the formatting string in place of {0}:
    class Student{
      override string ToString(){
        return this.LastName + ", " + this.FirstName;
      }
   }

There are some other more wacky things you could do, such as serializing to JSON, which will return a representation of the class suitable for computer consumption, but the basic thing here is that something needs to decide how your Student should be formatted and presented - and that's either the Student itself (override ToString() way), or the thing that knows about the Student.

Arguably, you could say it should be the class that holds the Student rather than the Student itself, because the Student itself can't possibly know how to format itself in all the myriad ways different things might want to see it

3 Comments

Hey Caius thanks for responding back to my question its good to know that I can do it like this, but I have to use the foreach loop in the program. How exactly would I go about that? I figured out the first and last name with it but am struggling on the studentID part, as 3 of the 5 students ID's are random. how would I call the ID's that are set and the random ones as well?
Just like you have been doing; I'm advocating adding a new method to your student class, it doesn't change your foreach loop at all- it just gives the WriteLine something to use that links up the names of the student. You can of course also change your WriteLine so that it uses a different way (get the name out of the item): Console.WriteLine("Student: {0}", item); becomes Console.WriteLine("Student: {0}", item.FirstName); for example
Oh ok I see what you were saying, sorry took my brain a minute to work there. Thanks Caius!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.