Friday 15 May 2015

List

A list<T> is very much like an arrayList, but instead of storing objects, it stores a defined type. Obviously polymorphisim applies, meaning that if your list can handle the type specified and any subtypes that derive from that type. 

to get started let's create a simple console application with an old-school main function.

dotnet new console -n pav.listExample --use-program-main

once that is done, let's open it up in code

code ./pavlistExample 

if you are using your terminal inside ms code, you can optionally add the -r tag to open your newly created console app in the current running instance of code.

code ./pav.listExample -r

your terminal would look something like this


When your application opens, you should be prompted to add some Build and Debug assets, make sure to click yes.



With that all out of the way, let's create our example:
  • create a base Person class that implements IComparable on the Person's age
  • create an employee class that inherits form our person class
in our main
  • create a list of people and fill it with both instances of Person and Employee
  • sort the list, the list will use the Person's implementation of IComparable

namespace pav.ListExample
{
    class Person : IComparable<Person>
    {
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }
        public Person(string Name, DateTime BirthDate) {
            this.Name = Name;
            this.BirthDate = BirthDate;
        }
        public int GetAge() {
            DateTime today = DateTime.Today;
            int age = today.Year - BirthDate.Year;
            return BirthDate > today.AddYears(-age) ? --age : age;
        }
        public virtual string Display() { return $"{Name} is {GetAge()}"; }
        public int CompareTo(Person? other)
        {
            if(other != null)
                return GetAge() - other.GetAge();
            return 0;
        }
    }

    class Employee : Person
    {
        static int _runningID;
        public int Id { get; private set; } = _runningID++;
        public Employee(string Name, DateTime BirthDate) : base(Name, BirthDate) {}

        public override string Display() { return $"{base.Display()} with id:{Id}"; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Person> l = new List<Person>();

            var p1 = new Person("Pavel", new DateTime(1984, 01, 31));
            var p2 = new Person("Tomek", new DateTime(1988, 08, 28));
            var p3 = new Person("Magda", new DateTime(1984, 06, 28));
            var e1 = new Employee("Marin", new DateTime(1983, 12, 04));
            var e2 = new Employee("Trish", new DateTime(1987, 05, 12));

            l.Add(p1);
            l.Add(p2);
            l.Add(p3);
            l.Add(e1);
            l.Add(e2);

            l.Sort();

            foreach (Person p in l)
                Console.WriteLine(p.Display());
        }
    }
}


Since our employee class derives from person our list can store both types, and since we marked our Display function as virtual when we override it in our Employee superclass when we call it on the list items we actually get the one defined in Employee instead of Person.


The above code implements IComparable so it'll sort the list of Persons and Employees youngest to oldest. if it didn't implement the interface it would just throw an exception