How can I print all the items from the list to the console in C#?

I am writing a code to get the output (read from a text file): "the list of people with instances like name, gender, age". However, when I ran the code, I got only the first line of the list in a text file. Here is my code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Person_Del
{
    class Program
    {
        public static void Main(String[] args)
        {
            Console.SetIn(new StreamReader("data.txt"));
            List<Person> p = new();
            string data = Console.ReadLine();
            Person obj = new();
            obj.SetData(data,"/");
            p.Add(obj);    
                foreach (var ii in p)
                {
                    Console.WriteLine(ii.GetInfo());
                }
        }
    }
    public class Person
    {
        //static methods
        public static void CheckData(string name, string gender, byte age)
        {
            string msg = null;
            if (string.IsNullOrEmpty(name)) msg += "Empty Name";
            if (string.IsNullOrEmpty(gender)) msg += (msg != null ? "; " : "") + "Empty Gender";
            if (age > 125) msg += (msg != null ? "; " : "") + $"Invalid age ({age})";
            if (msg != null) throw new Exception(msg);
        }
        public static (string, string, byte) Parse(string data, string delimiter)
        {
            try
            {
                string[] arr = data.Split(delimiter);
                string name = arr[0].Trim();
                string gender = arr[1].Trim();
                byte age = byte.Parse(arr[2]);
                return (name, gender, age);
            }
            catch (Exception)
            {
                throw new Exception($"Given data \"{data}\" are invalid.");
            }
        }

        //instance fields
        protected string name;
        protected string gender;
        protected byte age;

        //instance methods
        public string GetName() => name;
        public string GetGender() => gender;
        public byte GetAge() => age;

        public void SetData(string name, string gender, byte age)
        {
            Person.CheckData(name, gender, age);
            this.name = name;
            this.gender = gender;
            this.age = age;
        }
        public void SetData(string data, string delimiter)
        {
            (string, string, byte) value = Person.Parse(data, delimiter);
            string name = value.Item1;
            string gender = value.Item2;
            byte age = value.Item3;
            this.SetData(name, gender, age);
        }
        public string GetInfo() => $"Name:{name}, Gender:{gender}, Age:{age}";


        //new instance methods for homework
        public void SetName(string name) => this.name = name;
        public void SetGender(string gender) => this.gender = gender;

        internal bool SetData()
        {
            throw new NotImplementedException();
        }
    }
}

Here is my text file (data.txt):

Alice/F/23
David/M/23

Note that: I want to get the output of the two lines above; however, what I got is only the first line "Alice/F/23".


Solution 1:

By reading all the lines into an array first:

    public static void Main(String[] args)
    {
        var lines = File.ReadAllLines("data.txt");
        List<Person> people = new();
        foreach(var line in lines){
          Person p = new();
          p.SetData(line,"/");
          people.Add(obj); 
        }   
        foreach (var person in people )
        {
          Console.WriteLine(person.GetInfo());
        }
    }

By reading incrementally using a StreamReader:

    public static void Main(String[] args)
    {
        using var sr = new StreamReader("data.txt");
        List<Person> people = new();
        while(!sr.EndOfStream)
        {
          var line = sr.ReadLine();
          Person p = new();
          p.SetData(line,"/");
          people.Add(p); 
        }   
        foreach (var person in people)
        {
          Console.WriteLine(person.GetInfo());
        }
    }

The problem you're asking about ultimately stems from the fact that you only call ReadLine once, but I don't recommend stashing your StreamReader in Console's stdin.

I also named your variables a little better; strive for meaningful names - use plurals for lists and arrays etc. Short lived variables can be relatively meaningless, like Person p but longer lived ones/ones that are used in several places, try and make them so the code reads like a book: foreach(var person in people) rather than foreach(var ii in p)