diff --git a/vs4win/Chapter05/Chapter05.sln b/vs4win/Chapter05/Chapter05.sln
new file mode 100644
index 0000000..7b1dc96
--- /dev/null
+++ b/vs4win/Chapter05/Chapter05.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32210.308
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PacktLibrary", "PacktLibrary\PacktLibrary.csproj", "{9E796C3B-6FF6-4E0A-8B6D-A591B6FD1308}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeopleApp", "PeopleApp\PeopleApp.csproj", "{DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9E796C3B-6FF6-4E0A-8B6D-A591B6FD1308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9E796C3B-6FF6-4E0A-8B6D-A591B6FD1308}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E796C3B-6FF6-4E0A-8B6D-A591B6FD1308}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9E796C3B-6FF6-4E0A-8B6D-A591B6FD1308}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1A5D8950-33D6-47DC-B740-C193A5024C06}
+ EndGlobalSection
+EndGlobal
diff --git a/vs4win/Chapter05/PacktLibrary/BankAccount.cs b/vs4win/Chapter05/PacktLibrary/BankAccount.cs
new file mode 100644
index 0000000..6299ebd
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/BankAccount.cs
@@ -0,0 +1,8 @@
+namespace Packt.Shared;
+
+public class BankAccount
+{
+ public string? AccountName; // instance member
+ public decimal Balance; // instance member
+ public static decimal InterestRate; // shared member
+}
\ No newline at end of file
diff --git a/vs4win/Chapter05/PacktLibrary/Book.cs b/vs4win/Chapter05/PacktLibrary/Book.cs
new file mode 100644
index 0000000..b212a2a
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/Book.cs
@@ -0,0 +1,8 @@
+namespace Packt.Shared;
+
+public class Book
+{
+ // required is not working in .NET 7 Preview 1
+ public /* required */ string? Isbn { get; set; }
+ public string? Title { get; set; }
+}
diff --git a/vs4win/Chapter05/PacktLibrary/FlightPatterns.cs b/vs4win/Chapter05/PacktLibrary/FlightPatterns.cs
new file mode 100644
index 0000000..f582518
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/FlightPatterns.cs
@@ -0,0 +1,29 @@
+namespace Packt.Shared;
+
+public class BusinessClassPassenger
+{
+ public override string ToString()
+ {
+ return "Business Class";
+ }
+}
+
+public class FirstClassPassenger
+{
+ public int AirMiles { get; set; }
+
+ public override string ToString()
+ {
+ return $"First Class with {AirMiles:N0} air miles";
+ }
+}
+
+public class CoachClassPassenger
+{
+ public double CarryOnKG { get; set; }
+
+ public override string ToString()
+ {
+ return $"Coach Class with {CarryOnKG:N2} KG carry on";
+ }
+}
diff --git a/vs4win/Chapter05/PacktLibrary/PacktLibrary.csproj b/vs4win/Chapter05/PacktLibrary/PacktLibrary.csproj
new file mode 100644
index 0000000..95bce73
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/PacktLibrary.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+ 10
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter05/PacktLibrary/Person.cs b/vs4win/Chapter05/PacktLibrary/Person.cs
new file mode 100644
index 0000000..74fe344
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/Person.cs
@@ -0,0 +1,103 @@
+namespace Packt.Shared; // file-scoped namespace
+
+public partial class Person : object
+{
+ // fields
+ public string? Name;
+ public DateTime DateOfBirth;
+ public WondersOfTheAncientWorld FavoriteAncientWonder;
+ public WondersOfTheAncientWorld BucketList;
+ public List Children = new();
+
+ // constants
+ public const string Species = "Homo Sapiens";
+
+ // read-only fields
+ public readonly string HomePlanet = "Earth";
+ public readonly DateTime Instantiated;
+
+ // constructors
+ public Person()
+ {
+ // set default values for fields
+ // including read-only fields
+ Name = "Unknown";
+ Instantiated = DateTime.Now;
+ }
+
+ public Person(string initialName, string homePlanet)
+ {
+ Name = initialName;
+ HomePlanet = homePlanet;
+ Instantiated = DateTime.Now;
+ }
+
+ // methods
+ public void WriteToConsole()
+ {
+ WriteLine($"{Name} was born on a {DateOfBirth:dddd}.");
+ }
+
+ public string GetOrigin()
+ {
+ return $"{Name} was born on {HomePlanet}.";
+ }
+
+ public (string, int) GetFruit()
+ {
+ return ("Apples", 5);
+ }
+
+ public (string Name, int Number) GetNamedFruit()
+ {
+ return (Name: "Apples", Number: 5);
+ }
+
+ // deconstructors
+ public void Deconstruct(out string? name, out DateTime dob)
+ {
+ name = Name;
+ dob = DateOfBirth;
+ }
+
+ public void Deconstruct(out string? name,
+ out DateTime dob, out WondersOfTheAncientWorld fav)
+ {
+ name = Name;
+ dob = DateOfBirth;
+ fav = FavoriteAncientWonder;
+ }
+
+ public string SayHello()
+ {
+ return $"{Name} says 'Hello!'";
+ }
+
+ public string SayHello(string name)
+ {
+ return $"{Name} says 'Hello, {name}!'";
+ }
+
+ public string OptionalParameters(string command = "Run!",
+ double number = 0.0, bool active = true)
+ {
+ return string.Format(
+ format: "command is {0}, number is {1}, active is {2}",
+ arg0: command,
+ arg1: number,
+ arg2: active);
+ }
+
+ public void PassingParameters(int x, ref int y, out int z)
+ {
+ // out parameters cannot have a default
+ // AND must be initialized inside the method
+ z = 99;
+ // increment each parameter
+ x++;
+ y++;
+ z++;
+ }
+
+}
+
diff --git a/vs4win/Chapter05/PacktLibrary/PersonAutoGen.cs b/vs4win/Chapter05/PacktLibrary/PersonAutoGen.cs
new file mode 100644
index 0000000..4544f58
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/PersonAutoGen.cs
@@ -0,0 +1,153 @@
+namespace Packt.Shared;
+
+// this file simulates an autogenerated class
+
+public partial class Person
+{
+ // a readonly property defined using C# 1 - 5 syntax
+ public string Origin
+ {
+ get
+ {
+ return string.Format("{0} was born on {1}",
+ arg0: Name, arg1: HomePlanet);
+ }
+ }
+
+ // two readonly properties defined using C# 6+ lambda expression body syntax
+ public string Greeting => $"{Name} says 'Hello!'";
+ public int Age => DateTime.Today.Year - DateOfBirth.Year;
+
+ // a read-write property defined using C# 3.0 syntax
+ public string? FavoriteIceCream { get; set; } // auto-syntax
+
+ // a private field to store the property value
+ private string? favoritePrimaryColor;
+
+ // a public property to read and write to the field
+ public string? FavoritePrimaryColor
+ {
+ get
+ {
+ return favoritePrimaryColor;
+ }
+ set
+ {
+ switch (value?.ToLower())
+ {
+ case "red":
+ case "green":
+ case "blue":
+ favoritePrimaryColor = value;
+ break;
+ default:
+ throw new ArgumentException(
+ $"{value} is not a primary color. " +
+ "Choose from: red, green, blue.");
+ }
+ }
+ }
+
+ // indexers
+ public Person this[int index]
+ {
+ get
+ {
+ return Children[index]; // pass on to the List indexer
+ }
+ set
+ {
+ Children[index] = value;
+ }
+ }
+
+ public Person this[string name]
+ {
+ get
+ {
+ return Children.Find(p => p.Name == name);
+ }
+ set
+ {
+ Person found = Children.Find(p => p.Name == name);
+ if (found is not null) found = value;
+ }
+ }
+
+ private bool married = false;
+ public bool Married => married;
+
+ private Person? spouse = null;
+ public Person? Spouse => spouse;
+
+ // static method to marry
+ public static void Marry(Person p1, Person p2)
+ {
+ p1.Marry(p2);
+ }
+
+ // instance method to marry
+ public void Marry(Person partner)
+ {
+ if (married) return;
+ spouse = partner;
+ married = true;
+ partner.Marry(this);
+ }
+
+ // static method to "multiply"
+ public static Person Procreate(Person p1, Person p2)
+ {
+ if (p1.Spouse != p2)
+ {
+ throw new ArgumentException("You must be married to procreate.");
+ }
+
+ Person baby = new()
+ {
+ Name = $"Baby of {p1.Name} and {p2.Name}",
+ DateOfBirth = DateTime.Now
+ };
+
+ p1.Children.Add(baby);
+ p2.Children.Add(baby);
+
+ return baby;
+ }
+
+ // instance method to "multiply"
+ public Person ProcreateWith(Person partner)
+ {
+ return Procreate(this, partner);
+ }
+
+ // operator to "marry"
+ public static bool operator +(Person p1, Person p2)
+ {
+ Marry(p1, p2);
+ return p1.Married && p2.Married; // confirm they are both now married
+ }
+
+ // operator to "multiply"
+ public static Person operator *(Person p1, Person p2)
+ {
+ return Procreate(p1, p2);
+ }
+
+ // method with a local function
+ public static int Factorial(int number)
+ {
+ if (number < 0)
+ {
+ throw new ArgumentException(
+ $"{nameof(number)} cannot be less than zero.");
+ }
+ return localFactorial(number);
+
+ int localFactorial(int localNumber) // local function
+ {
+ if (localNumber == 0) return 1;
+ return localNumber * localFactorial(localNumber - 1);
+ }
+ }
+}
diff --git a/vs4win/Chapter05/PacktLibrary/Records.cs b/vs4win/Chapter05/PacktLibrary/Records.cs
new file mode 100644
index 0000000..bfb2a46
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/Records.cs
@@ -0,0 +1,7 @@
+namespace Packt.Shared;
+
+public class ImmutablePerson
+{
+ //public string? FirstName { get; init; }
+ //public string? LastName { get; init; }
+}
diff --git a/vs4win/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs b/vs4win/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs
new file mode 100644
index 0000000..a4b910e
--- /dev/null
+++ b/vs4win/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs
@@ -0,0 +1,14 @@
+namespace Packt.Shared;
+
+[Flags]
+public enum WondersOfTheAncientWorld : byte
+{
+ None = 0b_0000_0000, // i.e. 0
+ GreatPyramidOfGiza = 0b_0000_0001, // i.e. 1
+ HangingGardensOfBabylon = 0b_0000_0010, // i.e. 2
+ StatueOfZeusAtOlympia = 0b_0000_0100, // i.e. 4
+ TempleOfArtemisAtEphesus = 0b_0000_1000, // i.e. 8
+ MausoleumAtHalicarnassus = 0b_0001_0000, // i.e. 16
+ ColossusOfRhodes = 0b_0010_0000, // i.e. 32
+ LighthouseOfAlexandria = 0b_0100_0000 // i.e. 64
+}
diff --git a/vs4win/Chapter05/PeopleApp/PeopleApp.csproj b/vs4win/Chapter05/PeopleApp/PeopleApp.csproj
new file mode 100644
index 0000000..968b8d8
--- /dev/null
+++ b/vs4win/Chapter05/PeopleApp/PeopleApp.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter05/PeopleApp/Program.cs b/vs4win/Chapter05/PeopleApp/Program.cs
new file mode 100644
index 0000000..3a36ece
--- /dev/null
+++ b/vs4win/Chapter05/PeopleApp/Program.cs
@@ -0,0 +1,267 @@
+using Packt.Shared;
+
+Thread.CurrentThread.CurrentCulture =
+ System.Globalization.CultureInfo.GetCultureInfo("en-GB");
+
+// Person bob = new Person(); // C# 1.0 or later
+// var bob = new Person(); // C# 3.0 or later
+
+Person bob = new(); // C# 9.0 or later
+WriteLine(bob.ToString());
+
+bob.Name = "Bob Smith";
+bob.DateOfBirth = new DateTime(1965, 12, 22); // C# 1.0 or later
+
+WriteLine(format: "{0} was born on {1:dddd, d MMMM yyyy}",
+ arg0: bob.Name,
+ arg1: bob.DateOfBirth);
+
+Person alice = new()
+{
+ Name = "Alice Jones",
+ DateOfBirth = new(1998, 3, 7) // C# 9.0 or later
+};
+
+WriteLine(format: "{0} was born on {1:dd MMM yy}",
+ arg0: alice.Name,
+ arg1: alice.DateOfBirth);
+
+bob.FavoriteAncientWonder = WondersOfTheAncientWorld.StatueOfZeusAtOlympia;
+
+WriteLine(
+ format: "{0}'s favorite wonder is {1}. Its integer is {2}.",
+ arg0: bob.Name,
+ arg1: bob.FavoriteAncientWonder,
+ arg2: (int)bob.FavoriteAncientWonder);
+
+bob.BucketList =
+ WondersOfTheAncientWorld.HangingGardensOfBabylon
+ | WondersOfTheAncientWorld.MausoleumAtHalicarnassus;
+
+// bob.BucketList = (WondersOfTheAncientWorld)18;
+
+WriteLine($"{bob.Name}'s bucket list is {bob.BucketList}");
+
+bob.Children.Add(new Person { Name = "Alfred" }); // C# 3.0 and later
+bob.Children.Add(new() { Name = "Zoe" }); // C# 9.0 and later
+
+WriteLine($"{bob.Name} has {bob.Children.Count} children:");
+
+for (int childIndex = 0; childIndex < bob.Children.Count; childIndex++)
+{
+ WriteLine($"> {bob.Children[childIndex].Name}");
+}
+
+/*
+foreach (Person child in bob.Children)
+{
+ WriteLine($"> {child.Name}");
+}
+*/
+
+BankAccount.InterestRate = 0.012M; // store a shared value
+
+BankAccount jonesAccount = new();
+jonesAccount.AccountName = "Mrs. Jones";
+jonesAccount.Balance = 2400;
+WriteLine(format: "{0} earned {1:C} interest.",
+ arg0: jonesAccount.AccountName,
+ arg1: jonesAccount.Balance * BankAccount.InterestRate);
+
+BankAccount gerrierAccount = new();
+gerrierAccount.AccountName = "Ms. Gerrier";
+gerrierAccount.Balance = 98;
+WriteLine(format: "{0} earned {1:C} interest.",
+ arg0: gerrierAccount.AccountName,
+ arg1: gerrierAccount.Balance * BankAccount.InterestRate);
+
+WriteLine($"{bob.Name} is a {Person.Species}");
+
+WriteLine($"{bob.Name} was born on {bob.HomePlanet}");
+
+Person blankPerson = new();
+
+WriteLine(format:
+ "{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
+ arg0: blankPerson.Name,
+ arg1: blankPerson.HomePlanet,
+ arg2: blankPerson.Instantiated);
+
+Person gunny = new(initialName: "Gunny", homePlanet: "Mars");
+
+WriteLine(format:
+ "{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
+ arg0: gunny.Name,
+ arg1: gunny.HomePlanet,
+ arg2: gunny.Instantiated);
+
+bob.WriteToConsole();
+WriteLine(bob.GetOrigin());
+
+(string, int) fruit = bob.GetFruit();
+WriteLine($"{fruit.Item1}, {fruit.Item2} there are.");
+
+var fruitNamed = bob.GetNamedFruit();
+WriteLine($"There are {fruitNamed.Number} {fruitNamed.Name}.");
+
+var thing1 = ("Neville", 4);
+WriteLine($"{thing1.Item1} has {thing1.Item2} children.");
+
+var thing2 = (bob.Name, bob.Children.Count);
+WriteLine($"{thing2.Name} has {thing2.Count} children.");
+
+(string fruitName, int fruitNumber) = bob.GetFruit();
+WriteLine($"Deconstructed: {fruitName}, {fruitNumber}");
+
+// Deconstructing a Person
+var (name1, dob1) = bob;
+WriteLine($"Deconstructed: {name1}, {dob1}");
+
+var (name2, dob2, fav2) = bob;
+WriteLine($"Deconstructed: {name2}, {dob2}, {fav2}");
+
+WriteLine(bob.SayHello());
+WriteLine(bob.SayHello("Emily"));
+
+WriteLine(bob.OptionalParameters());
+
+WriteLine(bob.OptionalParameters("Jump!", 98.5));
+
+WriteLine(bob.OptionalParameters(number: 52.7, command: "Hide!"));
+
+WriteLine(bob.OptionalParameters("Poke!", active: false));
+
+int a = 10;
+int b = 20;
+int c = 30;
+WriteLine($"Before: a = {a}, b = {b}, c = {c}");
+bob.PassingParameters(a, ref b, out c);
+WriteLine($"After: a = {a}, b = {b}, c = {c}");
+
+int d = 10;
+int e = 20;
+WriteLine($"Before: d = {d}, e = {e}, f doesn't exist yet!");
+
+// simplified C# 7.0 or later syntax for the out parameter
+bob.PassingParameters(d, ref e, out int f);
+WriteLine($"After: d = {d}, e = {e}, f = {f}");
+
+Person sam = new()
+{
+ Name = "Sam",
+ DateOfBirth = new(1969, 6, 25)
+};
+
+WriteLine(sam.Origin);
+WriteLine(sam.Greeting);
+WriteLine(sam.Age);
+
+sam.FavoriteIceCream = "Chocolate Fudge";
+WriteLine($"Sam's favorite ice-cream flavor is {sam.FavoriteIceCream}.");
+sam.FavoritePrimaryColor = "Red";
+WriteLine($"Sam's favorite primary color is {sam.FavoritePrimaryColor}.");
+
+Book book = new();
+book.Title = "C# 11 and .NET 7 - Modern Cross-Platform Development";
+
+sam.Children.Add(new() { Name = "Charlie", DateOfBirth = new(2010, 3, 18) });
+sam.Children.Add(new() { Name = "Ella", DateOfBirth = new(2020, 12, 24) });
+
+// get using Children list
+WriteLine($"Sam's first child is {sam.Children[0].Name}.");
+WriteLine($"Sam's second child is {sam.Children[1].Name}.");
+
+// get using integer position indexer
+WriteLine($"Sam's first child is {sam[0].Name}.");
+WriteLine($"Sam's second child is {sam[1].Name}.");
+
+// get using name indexer
+WriteLine($"Sam's child named Ella is {sam["Ella"].Age} years old.");
+
+// Implementing functionality using methods
+
+Person lamech = new() { Name = "Lamech" };
+Person adah = new() { Name = "Adah" };
+Person zillah = new() { Name = "Zillah" };
+
+lamech.Marry(adah);
+// Person.Marry(zillah, lamech);
+if (zillah + lamech)
+{
+ WriteLine($"{zillah.Name} and {lamech.Name} successfully got married.");
+}
+
+WriteLine($"{lamech.Name} is married to {lamech.Spouse?.Name ?? "nobody"}");
+WriteLine($"{adah.Name} is married to {adah.Spouse?.Name ?? "nobody"}");
+WriteLine($"{zillah.Name} is married to {zillah.Spouse?.Name ?? "nobody"}");
+
+// call instance method
+Person baby1 = lamech.ProcreateWith(adah);
+baby1.Name = "Jabal";
+WriteLine($"{baby1.Name} was born on {baby1.DateOfBirth}");
+
+// call static method
+Person baby2 = Person.Procreate(zillah, lamech);
+baby2.Name = "Tubalcain";
+
+// use operator to "multiply"
+Person baby3 = lamech * adah;
+baby3.Name = "Jubal";
+
+Person baby4 = zillah * lamech;
+baby4.Name = "Naamah";
+
+WriteLine($"{lamech.Name} has {lamech.Children.Count} children.");
+WriteLine($"{adah.Name} has {adah.Children.Count} children.");
+WriteLine($"{zillah.Name} has {zillah.Children.Count} children.");
+
+for (int i = 0; i < lamech.Children.Count; i++)
+{
+ WriteLine(format: "{0}'s child #{1} is named \"{2}\".",
+ arg0: lamech.Name, arg1: i, arg2: lamech[i].Name);
+}
+
+// Implementing functionality using local functions
+
+WriteLine($"5! is {Person.Factorial(5)}");
+
+// Pattern matching with objects
+
+object[] passengers = {
+ new FirstClassPassenger { AirMiles = 1_419 },
+ new FirstClassPassenger { AirMiles = 16_562 },
+ new BusinessClassPassenger(),
+ new CoachClassPassenger { CarryOnKG = 25.7 },
+ new CoachClassPassenger { CarryOnKG = 0 },
+};
+
+foreach (object passenger in passengers)
+{
+ decimal flightCost = passenger switch
+ {
+ /* C# 8 syntax
+ FirstClassPassenger p when p.AirMiles > 35000 => 1500M,
+ FirstClassPassenger p when p.AirMiles > 15000 => 1750M,
+ FirstClassPassenger => 2000M, */
+
+ // C# 9 or later syntax
+ FirstClassPassenger p => p.AirMiles switch
+ {
+ > 35000 => 1500M,
+ > 15000 => 1750M,
+ _ => 2000M
+ },
+ BusinessClassPassenger _ => 1000M,
+ CoachClassPassenger p when p.CarryOnKG < 10.0 => 500M,
+ CoachClassPassenger _ => 650M,
+ _ => 800M
+ };
+ WriteLine($"Flight costs {flightCost:C} for {passenger}");
+}
+
+//ImmutablePerson jeff = new()
+//{
+// FirstName = "Jeff",
+// LastName = "Winger"
+//};
+//jeff.FirstName = "Geoff";
diff --git a/vscode/Chapter05/Chapter05.code-workspace b/vscode/Chapter05/Chapter05.code-workspace
new file mode 100644
index 0000000..9866d2f
--- /dev/null
+++ b/vscode/Chapter05/Chapter05.code-workspace
@@ -0,0 +1,10 @@
+{
+ "folders": [
+ {
+ "path": "PacktLibrary"
+ },
+ {
+ "path": "PeopleApp"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/vscode/Chapter05/PacktLibrary/BankAccount.cs b/vscode/Chapter05/PacktLibrary/BankAccount.cs
new file mode 100644
index 0000000..6299ebd
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/BankAccount.cs
@@ -0,0 +1,8 @@
+namespace Packt.Shared;
+
+public class BankAccount
+{
+ public string? AccountName; // instance member
+ public decimal Balance; // instance member
+ public static decimal InterestRate; // shared member
+}
\ No newline at end of file
diff --git a/vscode/Chapter05/PacktLibrary/Book.cs b/vscode/Chapter05/PacktLibrary/Book.cs
new file mode 100644
index 0000000..b212a2a
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/Book.cs
@@ -0,0 +1,8 @@
+namespace Packt.Shared;
+
+public class Book
+{
+ // required is not working in .NET 7 Preview 1
+ public /* required */ string? Isbn { get; set; }
+ public string? Title { get; set; }
+}
diff --git a/vscode/Chapter05/PacktLibrary/FlightPatterns.cs b/vscode/Chapter05/PacktLibrary/FlightPatterns.cs
new file mode 100644
index 0000000..f582518
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/FlightPatterns.cs
@@ -0,0 +1,29 @@
+namespace Packt.Shared;
+
+public class BusinessClassPassenger
+{
+ public override string ToString()
+ {
+ return "Business Class";
+ }
+}
+
+public class FirstClassPassenger
+{
+ public int AirMiles { get; set; }
+
+ public override string ToString()
+ {
+ return $"First Class with {AirMiles:N0} air miles";
+ }
+}
+
+public class CoachClassPassenger
+{
+ public double CarryOnKG { get; set; }
+
+ public override string ToString()
+ {
+ return $"Coach Class with {CarryOnKG:N2} KG carry on";
+ }
+}
diff --git a/vscode/Chapter05/PacktLibrary/PacktLibrary.csproj b/vscode/Chapter05/PacktLibrary/PacktLibrary.csproj
new file mode 100644
index 0000000..95bce73
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/PacktLibrary.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+ 10
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vscode/Chapter05/PacktLibrary/Person.cs b/vscode/Chapter05/PacktLibrary/Person.cs
new file mode 100644
index 0000000..74fe344
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/Person.cs
@@ -0,0 +1,103 @@
+namespace Packt.Shared; // file-scoped namespace
+
+public partial class Person : object
+{
+ // fields
+ public string? Name;
+ public DateTime DateOfBirth;
+ public WondersOfTheAncientWorld FavoriteAncientWonder;
+ public WondersOfTheAncientWorld BucketList;
+ public List Children = new();
+
+ // constants
+ public const string Species = "Homo Sapiens";
+
+ // read-only fields
+ public readonly string HomePlanet = "Earth";
+ public readonly DateTime Instantiated;
+
+ // constructors
+ public Person()
+ {
+ // set default values for fields
+ // including read-only fields
+ Name = "Unknown";
+ Instantiated = DateTime.Now;
+ }
+
+ public Person(string initialName, string homePlanet)
+ {
+ Name = initialName;
+ HomePlanet = homePlanet;
+ Instantiated = DateTime.Now;
+ }
+
+ // methods
+ public void WriteToConsole()
+ {
+ WriteLine($"{Name} was born on a {DateOfBirth:dddd}.");
+ }
+
+ public string GetOrigin()
+ {
+ return $"{Name} was born on {HomePlanet}.";
+ }
+
+ public (string, int) GetFruit()
+ {
+ return ("Apples", 5);
+ }
+
+ public (string Name, int Number) GetNamedFruit()
+ {
+ return (Name: "Apples", Number: 5);
+ }
+
+ // deconstructors
+ public void Deconstruct(out string? name, out DateTime dob)
+ {
+ name = Name;
+ dob = DateOfBirth;
+ }
+
+ public void Deconstruct(out string? name,
+ out DateTime dob, out WondersOfTheAncientWorld fav)
+ {
+ name = Name;
+ dob = DateOfBirth;
+ fav = FavoriteAncientWonder;
+ }
+
+ public string SayHello()
+ {
+ return $"{Name} says 'Hello!'";
+ }
+
+ public string SayHello(string name)
+ {
+ return $"{Name} says 'Hello, {name}!'";
+ }
+
+ public string OptionalParameters(string command = "Run!",
+ double number = 0.0, bool active = true)
+ {
+ return string.Format(
+ format: "command is {0}, number is {1}, active is {2}",
+ arg0: command,
+ arg1: number,
+ arg2: active);
+ }
+
+ public void PassingParameters(int x, ref int y, out int z)
+ {
+ // out parameters cannot have a default
+ // AND must be initialized inside the method
+ z = 99;
+ // increment each parameter
+ x++;
+ y++;
+ z++;
+ }
+
+}
+
diff --git a/vscode/Chapter05/PacktLibrary/PersonAutoGen.cs b/vscode/Chapter05/PacktLibrary/PersonAutoGen.cs
new file mode 100644
index 0000000..4544f58
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/PersonAutoGen.cs
@@ -0,0 +1,153 @@
+namespace Packt.Shared;
+
+// this file simulates an autogenerated class
+
+public partial class Person
+{
+ // a readonly property defined using C# 1 - 5 syntax
+ public string Origin
+ {
+ get
+ {
+ return string.Format("{0} was born on {1}",
+ arg0: Name, arg1: HomePlanet);
+ }
+ }
+
+ // two readonly properties defined using C# 6+ lambda expression body syntax
+ public string Greeting => $"{Name} says 'Hello!'";
+ public int Age => DateTime.Today.Year - DateOfBirth.Year;
+
+ // a read-write property defined using C# 3.0 syntax
+ public string? FavoriteIceCream { get; set; } // auto-syntax
+
+ // a private field to store the property value
+ private string? favoritePrimaryColor;
+
+ // a public property to read and write to the field
+ public string? FavoritePrimaryColor
+ {
+ get
+ {
+ return favoritePrimaryColor;
+ }
+ set
+ {
+ switch (value?.ToLower())
+ {
+ case "red":
+ case "green":
+ case "blue":
+ favoritePrimaryColor = value;
+ break;
+ default:
+ throw new ArgumentException(
+ $"{value} is not a primary color. " +
+ "Choose from: red, green, blue.");
+ }
+ }
+ }
+
+ // indexers
+ public Person this[int index]
+ {
+ get
+ {
+ return Children[index]; // pass on to the List indexer
+ }
+ set
+ {
+ Children[index] = value;
+ }
+ }
+
+ public Person this[string name]
+ {
+ get
+ {
+ return Children.Find(p => p.Name == name);
+ }
+ set
+ {
+ Person found = Children.Find(p => p.Name == name);
+ if (found is not null) found = value;
+ }
+ }
+
+ private bool married = false;
+ public bool Married => married;
+
+ private Person? spouse = null;
+ public Person? Spouse => spouse;
+
+ // static method to marry
+ public static void Marry(Person p1, Person p2)
+ {
+ p1.Marry(p2);
+ }
+
+ // instance method to marry
+ public void Marry(Person partner)
+ {
+ if (married) return;
+ spouse = partner;
+ married = true;
+ partner.Marry(this);
+ }
+
+ // static method to "multiply"
+ public static Person Procreate(Person p1, Person p2)
+ {
+ if (p1.Spouse != p2)
+ {
+ throw new ArgumentException("You must be married to procreate.");
+ }
+
+ Person baby = new()
+ {
+ Name = $"Baby of {p1.Name} and {p2.Name}",
+ DateOfBirth = DateTime.Now
+ };
+
+ p1.Children.Add(baby);
+ p2.Children.Add(baby);
+
+ return baby;
+ }
+
+ // instance method to "multiply"
+ public Person ProcreateWith(Person partner)
+ {
+ return Procreate(this, partner);
+ }
+
+ // operator to "marry"
+ public static bool operator +(Person p1, Person p2)
+ {
+ Marry(p1, p2);
+ return p1.Married && p2.Married; // confirm they are both now married
+ }
+
+ // operator to "multiply"
+ public static Person operator *(Person p1, Person p2)
+ {
+ return Procreate(p1, p2);
+ }
+
+ // method with a local function
+ public static int Factorial(int number)
+ {
+ if (number < 0)
+ {
+ throw new ArgumentException(
+ $"{nameof(number)} cannot be less than zero.");
+ }
+ return localFactorial(number);
+
+ int localFactorial(int localNumber) // local function
+ {
+ if (localNumber == 0) return 1;
+ return localNumber * localFactorial(localNumber - 1);
+ }
+ }
+}
diff --git a/vscode/Chapter05/PacktLibrary/Records.cs b/vscode/Chapter05/PacktLibrary/Records.cs
new file mode 100644
index 0000000..bfb2a46
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/Records.cs
@@ -0,0 +1,7 @@
+namespace Packt.Shared;
+
+public class ImmutablePerson
+{
+ //public string? FirstName { get; init; }
+ //public string? LastName { get; init; }
+}
diff --git a/vscode/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs b/vscode/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs
new file mode 100644
index 0000000..a4b910e
--- /dev/null
+++ b/vscode/Chapter05/PacktLibrary/WondersOfTheAncientWorld.cs
@@ -0,0 +1,14 @@
+namespace Packt.Shared;
+
+[Flags]
+public enum WondersOfTheAncientWorld : byte
+{
+ None = 0b_0000_0000, // i.e. 0
+ GreatPyramidOfGiza = 0b_0000_0001, // i.e. 1
+ HangingGardensOfBabylon = 0b_0000_0010, // i.e. 2
+ StatueOfZeusAtOlympia = 0b_0000_0100, // i.e. 4
+ TempleOfArtemisAtEphesus = 0b_0000_1000, // i.e. 8
+ MausoleumAtHalicarnassus = 0b_0001_0000, // i.e. 16
+ ColossusOfRhodes = 0b_0010_0000, // i.e. 32
+ LighthouseOfAlexandria = 0b_0100_0000 // i.e. 64
+}
diff --git a/vscode/Chapter05/PeopleApp/PeopleApp.csproj b/vscode/Chapter05/PeopleApp/PeopleApp.csproj
new file mode 100644
index 0000000..968b8d8
--- /dev/null
+++ b/vscode/Chapter05/PeopleApp/PeopleApp.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vscode/Chapter05/PeopleApp/Program.cs b/vscode/Chapter05/PeopleApp/Program.cs
new file mode 100644
index 0000000..3a36ece
--- /dev/null
+++ b/vscode/Chapter05/PeopleApp/Program.cs
@@ -0,0 +1,267 @@
+using Packt.Shared;
+
+Thread.CurrentThread.CurrentCulture =
+ System.Globalization.CultureInfo.GetCultureInfo("en-GB");
+
+// Person bob = new Person(); // C# 1.0 or later
+// var bob = new Person(); // C# 3.0 or later
+
+Person bob = new(); // C# 9.0 or later
+WriteLine(bob.ToString());
+
+bob.Name = "Bob Smith";
+bob.DateOfBirth = new DateTime(1965, 12, 22); // C# 1.0 or later
+
+WriteLine(format: "{0} was born on {1:dddd, d MMMM yyyy}",
+ arg0: bob.Name,
+ arg1: bob.DateOfBirth);
+
+Person alice = new()
+{
+ Name = "Alice Jones",
+ DateOfBirth = new(1998, 3, 7) // C# 9.0 or later
+};
+
+WriteLine(format: "{0} was born on {1:dd MMM yy}",
+ arg0: alice.Name,
+ arg1: alice.DateOfBirth);
+
+bob.FavoriteAncientWonder = WondersOfTheAncientWorld.StatueOfZeusAtOlympia;
+
+WriteLine(
+ format: "{0}'s favorite wonder is {1}. Its integer is {2}.",
+ arg0: bob.Name,
+ arg1: bob.FavoriteAncientWonder,
+ arg2: (int)bob.FavoriteAncientWonder);
+
+bob.BucketList =
+ WondersOfTheAncientWorld.HangingGardensOfBabylon
+ | WondersOfTheAncientWorld.MausoleumAtHalicarnassus;
+
+// bob.BucketList = (WondersOfTheAncientWorld)18;
+
+WriteLine($"{bob.Name}'s bucket list is {bob.BucketList}");
+
+bob.Children.Add(new Person { Name = "Alfred" }); // C# 3.0 and later
+bob.Children.Add(new() { Name = "Zoe" }); // C# 9.0 and later
+
+WriteLine($"{bob.Name} has {bob.Children.Count} children:");
+
+for (int childIndex = 0; childIndex < bob.Children.Count; childIndex++)
+{
+ WriteLine($"> {bob.Children[childIndex].Name}");
+}
+
+/*
+foreach (Person child in bob.Children)
+{
+ WriteLine($"> {child.Name}");
+}
+*/
+
+BankAccount.InterestRate = 0.012M; // store a shared value
+
+BankAccount jonesAccount = new();
+jonesAccount.AccountName = "Mrs. Jones";
+jonesAccount.Balance = 2400;
+WriteLine(format: "{0} earned {1:C} interest.",
+ arg0: jonesAccount.AccountName,
+ arg1: jonesAccount.Balance * BankAccount.InterestRate);
+
+BankAccount gerrierAccount = new();
+gerrierAccount.AccountName = "Ms. Gerrier";
+gerrierAccount.Balance = 98;
+WriteLine(format: "{0} earned {1:C} interest.",
+ arg0: gerrierAccount.AccountName,
+ arg1: gerrierAccount.Balance * BankAccount.InterestRate);
+
+WriteLine($"{bob.Name} is a {Person.Species}");
+
+WriteLine($"{bob.Name} was born on {bob.HomePlanet}");
+
+Person blankPerson = new();
+
+WriteLine(format:
+ "{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
+ arg0: blankPerson.Name,
+ arg1: blankPerson.HomePlanet,
+ arg2: blankPerson.Instantiated);
+
+Person gunny = new(initialName: "Gunny", homePlanet: "Mars");
+
+WriteLine(format:
+ "{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
+ arg0: gunny.Name,
+ arg1: gunny.HomePlanet,
+ arg2: gunny.Instantiated);
+
+bob.WriteToConsole();
+WriteLine(bob.GetOrigin());
+
+(string, int) fruit = bob.GetFruit();
+WriteLine($"{fruit.Item1}, {fruit.Item2} there are.");
+
+var fruitNamed = bob.GetNamedFruit();
+WriteLine($"There are {fruitNamed.Number} {fruitNamed.Name}.");
+
+var thing1 = ("Neville", 4);
+WriteLine($"{thing1.Item1} has {thing1.Item2} children.");
+
+var thing2 = (bob.Name, bob.Children.Count);
+WriteLine($"{thing2.Name} has {thing2.Count} children.");
+
+(string fruitName, int fruitNumber) = bob.GetFruit();
+WriteLine($"Deconstructed: {fruitName}, {fruitNumber}");
+
+// Deconstructing a Person
+var (name1, dob1) = bob;
+WriteLine($"Deconstructed: {name1}, {dob1}");
+
+var (name2, dob2, fav2) = bob;
+WriteLine($"Deconstructed: {name2}, {dob2}, {fav2}");
+
+WriteLine(bob.SayHello());
+WriteLine(bob.SayHello("Emily"));
+
+WriteLine(bob.OptionalParameters());
+
+WriteLine(bob.OptionalParameters("Jump!", 98.5));
+
+WriteLine(bob.OptionalParameters(number: 52.7, command: "Hide!"));
+
+WriteLine(bob.OptionalParameters("Poke!", active: false));
+
+int a = 10;
+int b = 20;
+int c = 30;
+WriteLine($"Before: a = {a}, b = {b}, c = {c}");
+bob.PassingParameters(a, ref b, out c);
+WriteLine($"After: a = {a}, b = {b}, c = {c}");
+
+int d = 10;
+int e = 20;
+WriteLine($"Before: d = {d}, e = {e}, f doesn't exist yet!");
+
+// simplified C# 7.0 or later syntax for the out parameter
+bob.PassingParameters(d, ref e, out int f);
+WriteLine($"After: d = {d}, e = {e}, f = {f}");
+
+Person sam = new()
+{
+ Name = "Sam",
+ DateOfBirth = new(1969, 6, 25)
+};
+
+WriteLine(sam.Origin);
+WriteLine(sam.Greeting);
+WriteLine(sam.Age);
+
+sam.FavoriteIceCream = "Chocolate Fudge";
+WriteLine($"Sam's favorite ice-cream flavor is {sam.FavoriteIceCream}.");
+sam.FavoritePrimaryColor = "Red";
+WriteLine($"Sam's favorite primary color is {sam.FavoritePrimaryColor}.");
+
+Book book = new();
+book.Title = "C# 11 and .NET 7 - Modern Cross-Platform Development";
+
+sam.Children.Add(new() { Name = "Charlie", DateOfBirth = new(2010, 3, 18) });
+sam.Children.Add(new() { Name = "Ella", DateOfBirth = new(2020, 12, 24) });
+
+// get using Children list
+WriteLine($"Sam's first child is {sam.Children[0].Name}.");
+WriteLine($"Sam's second child is {sam.Children[1].Name}.");
+
+// get using integer position indexer
+WriteLine($"Sam's first child is {sam[0].Name}.");
+WriteLine($"Sam's second child is {sam[1].Name}.");
+
+// get using name indexer
+WriteLine($"Sam's child named Ella is {sam["Ella"].Age} years old.");
+
+// Implementing functionality using methods
+
+Person lamech = new() { Name = "Lamech" };
+Person adah = new() { Name = "Adah" };
+Person zillah = new() { Name = "Zillah" };
+
+lamech.Marry(adah);
+// Person.Marry(zillah, lamech);
+if (zillah + lamech)
+{
+ WriteLine($"{zillah.Name} and {lamech.Name} successfully got married.");
+}
+
+WriteLine($"{lamech.Name} is married to {lamech.Spouse?.Name ?? "nobody"}");
+WriteLine($"{adah.Name} is married to {adah.Spouse?.Name ?? "nobody"}");
+WriteLine($"{zillah.Name} is married to {zillah.Spouse?.Name ?? "nobody"}");
+
+// call instance method
+Person baby1 = lamech.ProcreateWith(adah);
+baby1.Name = "Jabal";
+WriteLine($"{baby1.Name} was born on {baby1.DateOfBirth}");
+
+// call static method
+Person baby2 = Person.Procreate(zillah, lamech);
+baby2.Name = "Tubalcain";
+
+// use operator to "multiply"
+Person baby3 = lamech * adah;
+baby3.Name = "Jubal";
+
+Person baby4 = zillah * lamech;
+baby4.Name = "Naamah";
+
+WriteLine($"{lamech.Name} has {lamech.Children.Count} children.");
+WriteLine($"{adah.Name} has {adah.Children.Count} children.");
+WriteLine($"{zillah.Name} has {zillah.Children.Count} children.");
+
+for (int i = 0; i < lamech.Children.Count; i++)
+{
+ WriteLine(format: "{0}'s child #{1} is named \"{2}\".",
+ arg0: lamech.Name, arg1: i, arg2: lamech[i].Name);
+}
+
+// Implementing functionality using local functions
+
+WriteLine($"5! is {Person.Factorial(5)}");
+
+// Pattern matching with objects
+
+object[] passengers = {
+ new FirstClassPassenger { AirMiles = 1_419 },
+ new FirstClassPassenger { AirMiles = 16_562 },
+ new BusinessClassPassenger(),
+ new CoachClassPassenger { CarryOnKG = 25.7 },
+ new CoachClassPassenger { CarryOnKG = 0 },
+};
+
+foreach (object passenger in passengers)
+{
+ decimal flightCost = passenger switch
+ {
+ /* C# 8 syntax
+ FirstClassPassenger p when p.AirMiles > 35000 => 1500M,
+ FirstClassPassenger p when p.AirMiles > 15000 => 1750M,
+ FirstClassPassenger => 2000M, */
+
+ // C# 9 or later syntax
+ FirstClassPassenger p => p.AirMiles switch
+ {
+ > 35000 => 1500M,
+ > 15000 => 1750M,
+ _ => 2000M
+ },
+ BusinessClassPassenger _ => 1000M,
+ CoachClassPassenger p when p.CarryOnKG < 10.0 => 500M,
+ CoachClassPassenger _ => 650M,
+ _ => 800M
+ };
+ WriteLine($"Flight costs {flightCost:C} for {passenger}");
+}
+
+//ImmutablePerson jeff = new()
+//{
+// FirstName = "Jeff",
+// LastName = "Winger"
+//};
+//jeff.FirstName = "Geoff";