Example #1
0
        static void Main(string[] args)
        {
            var harry = new Person {
                Name = "Harry"
            };
            var mary = new Person {
                Name = "Mary"
            };
            var jill = new Person {
                Name = "Jill"
            };

            // call the instance method
            var baby1 = mary.ProcreateWith(harry);

            // call the static method
            var baby2 = Person.Procreate(harry, jill);

            // call an operator
            var baby3 = harry * mary;

            WriteLine($"{harry.Name} has {harry.Children.Count} children. ");
            WriteLine($"{mary.Name} has {mary.Children.Count} children. ");
            WriteLine($"{jill.Name} has {jill.Children.Count} children. ");

            WriteLine(
                format: "{0}'s first child is named \"{1}\".",
                arg0: harry.Name,
                arg1: harry.Children[0].Name
                );

            WriteLine($"5! is {Person.Factorial(5)}");

            // defining and hanlding delegates
            harry.Shout = Harry_Shout;
            harry.Poke();
            harry.Poke();
            harry.Poke();
            harry.Poke();

            Person[] people =
            {
                new Person {
                    Name = "Simon"
                },
                new Person {
                    Name = "Jenny"
                },
                new Person {
                    Name = "Adam"
                },
                new Person {
                    Name = "Richard"
                },
            };
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }
            // Use Person's IComparable implmentation to sort:
            WriteLine("Use Person's IComparable implementatjoin to sort:");
            Array.Sort(people);
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            WriteLine("use PersonComparer's IComparer implementation to sort:");
            Array.Sort(people, new PersonComparer());
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            // working with generic types
            // pre C# 2.0
            var t1 = new Thing();

            t1.Data = 42;
            WriteLine($"Thing with an integer: {t1.Process(42)}");

            var t2 = new Thing();

            t2.Data = "apple";
            WriteLine($"Thing with a string: {t2.Process("apple")}");

            // C# 2.0
            var gt1 = new GenericThing <int>();

            gt1.Data = 42;
            WriteLine($"GenericThing with an integer: {gt1.Process(42)}");

            var gt2 = new GenericThing <string>();

            gt2.Data = "apple";
            WriteLine($"GenericThing with a string: {gt2.Process("apple")}");

            // working with generic methods
            string number1 = "4";

            WriteLine(
                format: "{0} squared is {1}",
                arg0: number1,
                arg1: Squarer.Square <string>(number1)
                );

            byte number2 = 3;

            WriteLine(
                format: "{0} squared is {1}",
                arg0: number2,
                arg1: Squarer.Square <byte>(number2)
                );

            // working with struct types
            var dv1 = new DisplacementVector(3, 5);
            var dv2 = new DisplacementVector(-2, 7);
            var dv3 = dv1 + dv2;

            WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X}, {dv3.Y})");

            // Inheriting from classes
            Employee john = new Employee
            {
                Name        = "John Jones",
                DateOfBirth = new DateTime(1990, 7, 28)
            };

            john.EmployeeCode = "JJ001";
            john.HireDate     = new DateTime(2014, 11, 23);
            john.WriteToConsole();
            WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yyyy}");
            WriteLine(john.ToString());

            // understanding polymorphism
            Employee aliceInEmployee = new Employee
            {
                Name         = "Alice",
                EmployeeCode = "AA123"
            };
            Person aliceInPerson = aliceInEmployee;

            aliceInEmployee.WriteToConsole();                 // Employee.WriteToConsole()
            aliceInPerson.WriteToConsole();                   // Person.WriteToConsole()
            WriteLine(aliceInEmployee.ToString());            // Employee ToString()
            WriteLine(aliceInPerson.ToString());              // Employee override ToString()
            Employee explicitAlice = (Employee)aliceInPerson; // same as below

            //Employee aliceAsEmployee = aliceInPerson as Employee; // same as above
            if (aliceInPerson is Employee)
            {
                WriteLine($"{nameof(aliceInPerson)} IS an Employee");
            }

            // inheriting expceptions
            try
            {
                john.TimeTravel(new DateTime(1999, 12, 31));
                john.TimeTravel(new DateTime(1950, 12, 25));
            }
            catch (PersonException ex)
            {
                WriteLine(ex.Message);
            }

            // using static methods to reuse functionality
            // public bool IsValidEmail(this string input)
            //public static bool IsValidEmail(this string input)
            string email1 = "*****@*****.**";
            string email2 = "ian&test.com";

            WriteLine(
                format: "{0} is a valid e-mail address: {1}",
                arg0: email1,
                arg1: StringExtensions.IsValidEmail(email1)
                );
            WriteLine(
                format: "{0} is a valid e-mail address: {1}",
                arg0: email2,
                arg1: StringExtensions.IsValidEmail(email2)
                );
            // using extension methods to reuse functionality (see LINQ for powerful uses of extensions)
            //public static bool IsValidEmail(this string input)
            WriteLine(
                format: "{0} is a valid e-mail address: {1}",
                arg0: email1,
                arg1: email1.IsValidEmail()
                );
            WriteLine(
                format: "{0} is a valid e-mail address: {1}",
                arg0: email2,
                arg1: email2.IsValidEmail()
                );
        }
        static void Main(string[] args)
        {
            var harry = new Person {
                Name = "Harry"
            };
            var mary = new Person {
                Name = "Mary"
            };
            var jill = new Person {
                Name = "Jill"
            };

            // Implementing functionality using methods and operators

            // call instance method
            var baby1 = mary.ProcreateWith(harry);

            // call static method
            var baby2 = Person.Procreate(harry, jill);

            // call an operator
            var baby3 = harry * mary;

            WriteLine($"{harry.Name} has {harry.Children.Count} children.");
            WriteLine($"{mary.Name} has {mary.Children.Count} children.");
            WriteLine($"{jill.Name} has {jill.Children.Count} children.");

            WriteLine(
                format: "{0}'s first child is named \"{1}\".",
                arg0: harry.Name,
                arg1: harry.Children[0].Name);

            // Implementing functionality using local functions

            WriteLine($"5! is {Person.Factorial(5)}");

            // Raising and handling events

            harry.Shout += Harry_Shout;

            harry.Poke();
            harry.Poke();
            harry.Poke();
            harry.Poke();

            // Comparing objects when sorting

            Person[] people =
            {
                new Person {
                    Name = "Simon"
                },
                new Person {
                    Name = "Jenny"
                },
                new Person {
                    Name = "Adam"
                },
                new Person {
                    Name = "Richard"
                }
            };

            WriteLine("Initial list of people:");
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            WriteLine("Use Person's IComparable implementation to sort:");
            Array.Sort(people);
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            // Comparing objects using a separate class

            WriteLine("Use PersonComparer's IComparer implementation to sort:");
            Array.Sort(people, new PersonComparer());
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            // Working with generic types

            var t1 = new Thing();

            t1.Data = 42;
            WriteLine($"Thing with an integer: {t1.Process(42)}");

            var t2 = new Thing();

            t2.Data = "apple";
            WriteLine($"Thing with a string: {t2.Process("apple")}");

            var gt1 = new GenericThing <int>();

            gt1.Data = 42;
            WriteLine($"GenericThing with an integer: {gt1.Process(42)}");

            var gt2 = new GenericThing <string>();

            gt2.Data = "apple";
            WriteLine($"GenericThing with a string: {gt2.Process("apple")}");

            // Working with generic methods

            string number1 = "4";

            WriteLine("{0} squared is {1}",
                      arg0: number1,
                      arg1: Squarer.Square <string>(number1));

            byte number2 = 3;

            WriteLine("{0} squared is {1}",
                      arg0: number2,
                      arg1: Squarer.Square(number2));

            // Working with struct types

            var dv1 = new DisplacementVector(3, 5);
            var dv2 = new DisplacementVector(-2, 7);
            var dv3 = dv1 + dv2;

            WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X}, {dv3.Y})");

            // Inheriting from classes

            Employee john = new Employee
            {
                Name        = "John Jones",
                DateOfBirth = new DateTime(1990, 7, 28)
            };

            john.WriteToConsole();

            // Extending classes

            john.EmployeeCode = "JJ001";
            john.HireDate     = new DateTime(2014, 11, 23);
            WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yy}");

            // Overriding  members

            WriteLine(john.ToString());

            // Understanding polymorphism

            Employee aliceInEmployee = new Employee
            {
                Name = "Alice", EmployeeCode = "AA123"
            };

            Person aliceInPerson = aliceInEmployee;

            aliceInEmployee.WriteToConsole();

            aliceInPerson.WriteToConsole();

            WriteLine(aliceInEmployee.ToString());

            WriteLine(aliceInPerson.ToString());

            // Explicit casting

            if (aliceInPerson is Employee)
            {
                WriteLine($"{nameof(aliceInPerson)} IS an Employee");

                Employee explicitAlice = (Employee)aliceInPerson;
                // safely do something with explicitAlice
            }

            Employee aliceAsEmployee = aliceInPerson as Employee;

            if (aliceAsEmployee != null)
            {
                WriteLine($"{nameof(aliceInPerson)} AS an Employee");
                // do something with aliceInEmployee
            }

            // Inheriting exceptions

            try
            {
                john.TimeTravel(new DateTime(1999, 12, 31));
                john.TimeTravel(new DateTime(1950, 12, 25));
            }
            catch (PersonException ex)
            {
                WriteLine(ex.Message);
            }

            // Using static methods to reuse functionality

            string email1 = "*****@*****.**";
            string email2 = "ian&test.com";

            WriteLine(
                "{0} is a valid e-mail address: {1}",
                arg0: email1,
                arg1: StringExtensions.IsValidEmail(email1));

            WriteLine(
                "{0} is a valid e-mail address: {1}",
                arg0: email2,
                arg1: StringExtensions.IsValidEmail(email2));

            WriteLine(
                "{0} is a valid e-mail address: {1}",
                arg0: email1,
                arg1: email1.IsValidEmail());

            WriteLine(
                "{0} is a valid e-mail address: {1}",
                arg0: email2,
                arg1: email2.IsValidEmail());
        }
        static void Main(string[] args)
        {
            var harry = new Person {
                Name = "Harry"
            };
            var mary = new Person {
                Name = "Mary"
            };
            var jill = new Person {
                Name = "Jill"
            };

            var baby1 = mary.ProcreateWith(harry);

            baby1.Name = "Gary";
            var baby2 = Person.Procreate(harry, jill);
            var baby3 = harry * mary;

            WriteLine($"{harry.Name} has {harry.Children.Count} children.");
            WriteLine($"{mary.Name} has {mary.Children.Count} children.");
            WriteLine($"{jill.Name} has {jill.Children.Count} children.");
            WriteLine(
                format: "{0}'s first child is named \"{1}\".",
                arg0: harry.Name,
                arg1: harry.Children[0].Name);

            WriteLine($"5! is {Person.Factorial(5)}");

            harry.Shout += Harry_Shout;
            harry.Poke();
            harry.Poke();
            harry.Poke();
            harry.Poke();

            Person[] people =
            {
                new Person {
                    Name = "Simon"
                },
                new Person {
                    Name = "Jenny"
                },
                new Person {
                    Name = "Adam"
                },
                new Person {
                    Name = "Richard"
                }
            };
            WriteLine("Initial list of people:");
            foreach (var person in people)
            {
                WriteLine($"  {person.Name}");
            }

            WriteLine("Use Person's IComparable implementation to sort:");
            Array.Sort(people);
            foreach (var person in people)
            {
                WriteLine($"  {person.Name}");
            }

            var t1 = new Thing();

            t1.Data = 42;
            WriteLine($"Thing with an integer: {t1.Process(42)}");

            var t2 = new Thing();

            t2.Data = "apple";
            WriteLine($"Thing with a string: {t2.Process("apple")}");

            var gt1 = new GenericThing <int>();

            gt1.Data = 42;
            WriteLine($"GenericThing with an integer: {gt1.Process(42)}");

            var gt2 = new GenericThing <string>();

            gt2.Data = "apple";
            WriteLine($"GenericThing with a string: {gt2.Process("apple")}");

            string number1 = "4";

            WriteLine("{0} squared is {1}", arg0: number1, arg1: Squarer.Square <string>(number1));

            byte number2 = 3;

            WriteLine("{0} squared is {1}", arg0: number2, arg1: Squarer.Square <byte>(number2));

            var dv1 = new DisplacementVector(3, 5);
            var dv2 = new DisplacementVector(-2, 7);
            var dv3 = dv1 + dv2;

            WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X}, {dv3.Y})");

            Employee john = new Employee {
                Name        = "John Jones",
                DateOfBirth = new DateTime(1990, 7, 28)
            };

            john.WriteToConsole();
            john.EmployeeCode = "JJ001";
            john.HireDate     = new DateTime(2014, 11, 23);
            WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yy}");

            WriteLine(john.ToString());

            Employee aliceInEmployee = new Employee
            {
                Name = "Alice", EmployeeCode = "AA123"
            };
            Person aliceInPerson = aliceInEmployee;

            aliceInEmployee.WriteToConsole();
            aliceInPerson.WriteToConsole();
            WriteLine(aliceInEmployee.ToString());
            WriteLine(aliceInPerson.ToString());

            if (aliceInPerson is Employee)
            {
                WriteLine($"{nameof(aliceInPerson)} IS an Employee");
                Employee explicitAlice = (Employee)aliceInPerson;
            }
            Employee aliceAsEmployee = aliceInPerson as Employee;

            if (aliceAsEmployee != null)
            {
                WriteLine($"{nameof(aliceInPerson)} AS an Employee");
            }

            try {
                john.TimeTravel(new DateTime(1999, 12, 31));
                john.TimeTravel(new DateTime(1950, 12, 25));
            }
            catch (PersonException ex) {
                WriteLine(ex.Message);
            }

            string email1 = "*****@*****.**";
            string email2 = "ian&test.com";

            WriteLine("{0} is a valid e-mail address: {1}",
                      arg0: email1,
                      arg1: StringExtensions.IsValidEmail(email1));

            WriteLine("{0} is a valid e-mail address: {1}",
                      arg0: email2,
                      arg1: StringExtensions.IsValidEmail(email2));
        }
        static void Main(string[] args)
        {
            var harry = new Person("Harry");
            var mary  = new Person("Mary");
            var jill  = new Person("Jill");

            var baby1 = mary.ProcreateWith(harry);
            var baby2 = Person.Procreate(harry, jill);
            // multiply operator overloaded with the Person class:
            var baby3 = harry * mary;

            WriteLine($"{harry.Name} has {harry.Children.Count} children.");
            WriteLine($"{mary.Name} has {mary.Children.Count} children.");
            WriteLine($"{jill.Name} has {jill.Children.Count} children.");
            WriteLine(
                format: "{0}'s first child is called {1}",
                arg0: harry.Name,
                arg1: harry.Children[0].Name
                );

            WriteLine($"5! is {Person.Factorial(5)}");


            // assign the method defined in this program to the delegate field
            // note: delegates are multicast so can assign multiple delegates to a single delegate field although no control as to order called
            // so could have used += operator instead of just the = assignment operator (book page 189)
            harry.Shout += Harry_Shout;

            harry.Poke();
            harry.Poke();
            harry.Poke();
            harry.Poke();

            // BOOK: page 192 INTERFACES
            Person[] people =
            {
                new Person("Simon"),
                new Person("Jenny"),
                new Person("Adam"),
                new Person("Richard")
            };

            WriteLine("People unsorted: ");
            foreach (var person in people)
            {
                Write($"{person.Name} ");
            }
            WriteLine();

            WriteLine("People sorted - uses IComparable implementation to sort: ");
            Array.Sort(people);
            foreach (var person in people)
            {
                Write($"{person.Name} ");
            }
            WriteLine();


            WriteLine("People sorted - uses PersonComparer (implements IComparer) class sort: ");
            Array.Sort(people, new PersonComparer());
            foreach (var person in people)
            {
                Write($"{person.Name} ");
            }
            WriteLine();

            // BOOK: page 198 making types safely reusable with GENERICS
            var t1 = new Thing();

            t1.Data = 42;
            WriteLine($"Thing with an integer: {t1.Process(42)}");

            var t2 = new Thing();

            t2.Data = "apple";
            WriteLine($"Thing with an string: {t2.Process("apple")}");

            // on instantiating instance of generic type, must pass a type parameter
            var gt1 = new GenericThing <int>();

            gt1.Data = 42;
            WriteLine($"GenericThing with an integer: {gt1.Process(42)}");

            var gt2 = new GenericThing <string>();

            gt2.Data = "apple";
            WriteLine($"GenericThing with an string: {gt2.Process("apple")}");

            string number1 = "4";

            WriteLine("{0} squared is {1}",
                      arg0: number1,
                      arg1: Squarer.Square <string>(number1));

            byte number2 = 3;

            WriteLine("{0} squared is {1}",
                      arg0: number1,
                      arg1: Squarer.Square <byte>(number2));

            var vector1 = new DisplacementVector(3, 4);
            var vector2 = new DisplacementVector(-2, 1);
            var vector3 = vector1 + vector2;

            WriteLine($"vector3: {vector3.X}, {vector3.Y}");

            Employee john = new Employee
            {
                Name        = "John Jones",
                DateOfBirth = new DateTime(1990, 7, 28)
            };

            john.WriteToConsole();
            john.EmployeeCode = "JJ001";
            john.HireDate     = new DateTime(2014, 11, 23);
            WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yy} with code {john.EmployeeCode}");

            WriteLine(john.ToString());
            WriteLine();

            // BOOK: page 212 Understanding polymorphism ---------------------------------------------------------------------

            // implicit casting section ****
            // an instance of a derived type (Employee) can be stored in a variable of the base type (Person) - IMPLICIT CASTING
            Employee aliceEmployee = new Employee {
                Name = "Alice", EmployeeCode = "AA123"
            };
            Person alicePerson = aliceEmployee;  // IMPLICIT casting

            WriteLine("Understanding Polymorphism section: ");
            WriteLine("alicePerson has just been assigned to aliceEmployee i.e. alicePerson = aliceEmployee");
            WriteLine();
            WriteLine("Now calling aliceEmployee.WriteToConsole(), then alicePerson.WriteToConsole()");
            aliceEmployee.WriteToConsole();                                             // Employee.WriteToConsole(): Alice was born on 01/01/01 and hired on 01/01/01
            alicePerson.WriteToConsole();                                               // Person.WriteToConsole(): Alice was born on a Monday
            WriteLine("Calling aliceEmployee.ToString(): " + aliceEmployee.ToString()); // Employee.ToString(): Alice's code is AA123
            WriteLine("Calling alicePerson.ToString(): " + alicePerson.ToString());     // Employee.ToString(): Alice's code is AA123

            // explicit casting section - and avoiding Casting Exceptions two options: use 'is' or 'as' keywords ****

            // use keyword 'is'
            if (alicePerson is Employee)
            {
                WriteLine($"{nameof(alicePerson)} IS an Employee - because of earlier assignment: alicePerson = aliceEmployee");
                // safe to cast
                Employee explicitAlice = (Employee)alicePerson;
            }

            Employee aliceAsEmployee = alicePerson as Employee; // keyword 'as' used to explicity cast --> need to check for null though

            if (aliceAsEmployee != null)
            {
                WriteLine($"{nameof(alicePerson)} AS an Employee - because of earlier assignment: Employee aliceAsEmployee = alicePerson as Employee");
            }



            // BOOK: page 216 Inheriting exceptions  ---------------------------------------------------------------------
            try
            {
                john.TimeTravel(new DateTime(1999, 12, 31));
                john.TimeTravel(new DateTime(1950, 12, 25));
            }
            catch (PersonException ex)
            {
                WriteLine(ex.Message);
            }



            // BOOK: page 218 Extending types when you cannot inherit (sealed)   ---------------------------------------------------------------------
            string email1 = "*****@*****.**";
            string email2 = "test&test.com";

            WriteLine("{0} is a valid email address: {1}",
                      arg0: email1,
                      arg1: StringExtensions.IsValidEmail(email1));

            WriteLine("{0} is a valid email address: {1}",
                      arg0: email2,
                      arg1: StringExtensions.IsValidEmail(email2));

            WriteLine("{0} is a valid email address: {1}",
                      arg0: email1,
                      arg1: email1.IsValidEmail());

            WriteLine("{0} is a valid email address: {1}",
                      arg0: email2,
                      arg1: email2.IsValidEmail());
        }
Example #5
0
        static void Main(string[] args)
        {
            var harry = new Person {
                Name = "Harry"
            };
            var mary = new Person {
                Name = "Mary"
            };
            var jill = new Person {
                Name = "Jill"
            };

            // call instance method
            var baby1 = mary.ProcreateWith(harry);

            // call static method
            var baby2 = Person.Procreate(harry, jill);

            // call an operator
            var baby3 = harry * mary;

            WriteLine($"{mary.Name} has {mary.Children.Count} children.");
            WriteLine($"{harry.Name} has {harry.Children.Count} children.");
            WriteLine($"{jill.Name} has {jill.Children.Count} children.");
            WriteLine($"{mary.Name}'s first child is named \"{mary.Children[0].Name}\".");
            WriteLine($"5! is {Person.Factorial(5)}");

            harry.Shout += Harry_Shout;
            harry.Poke();
            harry.Poke();
            harry.Poke();
            harry.Poke();

            Person[] people =
            {
                new Person {
                    Name = "Juliani"
                },
                new Person {
                    Name = "Simon"
                },
                new Person {
                    Name = "Zoraide"
                },
                new Person {
                    Name = "Alan"
                },
                new Person {
                    Name = "Pedro"
                },
                new Person {
                    Name = "Beatriz"
                }
            };

            WriteLine("Initial list of people: ");
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            WriteLine("Use Person's IComparable implementation to sort: ");
            Array.Sort(people);
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            WriteLine("Use PersonComparer's IComparer implementation to sort:");
            Array.Sort(people, new PersonComparer());
            foreach (var person in people)
            {
                WriteLine($"{person.Name}");
            }

            var t = new Thing();

            t.Data = 42;
            WriteLine($"Thing: {t.Process("42")}");

            var gt = new GenericThing <int>();

            gt.Data = 42;
            WriteLine($"GenericThing: {gt.Process("42")}");

            string number1 = "4";

            WriteLine($"{number1} squared is {Squarer.Square<string>(number1)}");
            byte number2 = 3;

            WriteLine($"{number2} squared is {Squarer.Square<byte>(number2)}");


            var dv1 = new DisplacementVector(3, 5);
            var dv2 = new DisplacementVector(-2, 7);
            var dv3 = dv1 + dv2;

            WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X},{dv3.Y})");

            Employee e1 = new Employee {
                Name        = "John Jones",
                DateOfBirth = new DateTime(1990, 7, 28)
            };

            e1.WriteToConsole();

            e1.EmployeeCode = "JJ001";
            e1.HireDate     = new DateTime(2014, 11, 23);
            WriteLine($"{e1.Name} was hired on {e1.HireDate:dd/MM/yy}");
            WriteLine(e1.ToString());

            Employee aliceInEmployee = new Employee {
                Name = "Alice", EmployeeCode = "AA123"
            };
            Person aliceInPerson = aliceInEmployee;

            aliceInEmployee.WriteToConsole();
            aliceInPerson.WriteToConsole();
            WriteLine(aliceInEmployee.ToString());
            WriteLine(aliceInPerson.ToString());

            if (aliceInPerson is Employee)
            {
                WriteLine($"{nameof(aliceInPerson)} IS an Employee");
                Employee e2 = (Employee)aliceInPerson;
                // do something with e2
            }
            Employee e3 = aliceInPerson as Employee;

            if (e3 != null)
            {
                WriteLine($"{nameof(aliceInPerson)} AS an Employee");
                // do something with e3
            }

            try {
                e1.TimeTravel(new DateTime(1999, 12, 31));
                e1.TimeTravel(new DateTime(1950, 12, 25));
            }
            catch (PersonException ex) {
                WriteLine(ex.Message);
            }

            string email1 = "*****@*****.**";
            string email2 = "ian&test.com";

            WriteLine($"{email1} is a valid e-mail address: {StringExtensions.IsValidEmail(email1)}.");
            WriteLine($"{email2} is a valid e-mail address: {StringExtensions.IsValidEmail(email2)}.");

            WriteLine($"{email1} is a valid e-mail address:{email1.IsValidEmail()}.");
            WriteLine($"{email2} is a valid e-mail address:{email2.IsValidEmail()}.");
        }