diff --git a/vs4win/Chapter05/Chapter05.sln b/vs4win/Chapter05/Chapter05.sln
index 7b1dc96..68d6e4b 100644
--- a/vs4win/Chapter05/Chapter05.sln
+++ b/vs4win/Chapter05/Chapter05.sln
@@ -3,9 +3,11 @@ 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}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PeopleApp", "PeopleApp\PeopleApp.csproj", "{DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Namespaces", "Namespaces\Namespaces.csproj", "{AA8F156C-1105-4AB2-8C42-637990E44EB4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{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
+ {AA8F156C-1105-4AB2-8C42-637990E44EB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA8F156C-1105-4AB2-8C42-637990E44EB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AA8F156C-1105-4AB2-8C42-637990E44EB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA8F156C-1105-4AB2-8C42-637990E44EB4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/vs4win/Chapter05/Namespaces/France.Paris.cs b/vs4win/Chapter05/Namespaces/France.Paris.cs
new file mode 100644
index 0000000..af7e47d
--- /dev/null
+++ b/vs4win/Chapter05/Namespaces/France.Paris.cs
@@ -0,0 +1,6 @@
+namespace France
+{
+ public class Paris
+ {
+ }
+}
diff --git a/vs4win/Chapter05/Namespaces/Namespaces.csproj b/vs4win/Chapter05/Namespaces/Namespaces.csproj
new file mode 100644
index 0000000..cd63b28
--- /dev/null
+++ b/vs4win/Chapter05/Namespaces/Namespaces.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter05/Namespaces/Program.cs b/vs4win/Chapter05/Namespaces/Program.cs
new file mode 100644
index 0000000..f5b80fb
--- /dev/null
+++ b/vs4win/Chapter05/Namespaces/Program.cs
@@ -0,0 +1,10 @@
+using France;
+using us = Texas; // us becomes alias for the namespace and it is not imported
+using Env = System.Environment;
+
+Paris p1 = new();
+us.Paris p2 = new();
+
+WriteLine(Env.OSVersion);
+WriteLine(Env.MachineName);
+WriteLine(Env.CurrentDirectory);
\ No newline at end of file
diff --git a/vs4win/Chapter05/Namespaces/Texas.Paris.cs b/vs4win/Chapter05/Namespaces/Texas.Paris.cs
new file mode 100644
index 0000000..9ece88d
--- /dev/null
+++ b/vs4win/Chapter05/Namespaces/Texas.Paris.cs
@@ -0,0 +1,6 @@
+namespace Texas
+{
+ public class Paris
+ {
+ }
+}
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj b/vs4win/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj
new file mode 100644
index 0000000..cd63b28
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Circle.cs b/vs4win/Chapter06/Ch06Ex02Inheritance/Circle.cs
new file mode 100644
index 0000000..861431c
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Circle.cs
@@ -0,0 +1,29 @@
+namespace Packt.Shared;
+
+public class Circle : Square
+{
+ public Circle() { }
+
+ public Circle(double radius) : base(width: radius * 2) { }
+
+ public double Radius
+ {
+ get
+ {
+ return height / 2;
+ }
+ set
+ {
+ Height = value * 2;
+ }
+ }
+
+ public override double Area
+ {
+ get
+ {
+ double radius = height / 2;
+ return Math.PI * radius * radius;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Program.cs b/vs4win/Chapter06/Ch06Ex02Inheritance/Program.cs
new file mode 100644
index 0000000..5558cfe
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Program.cs
@@ -0,0 +1,10 @@
+using Packt.Shared;
+
+Rectangle r = new(height: 3, width: 4.5);
+WriteLine($"Rectangle H: {r.Height}, W: {r.Width}, Area: {r.Area}");
+
+Square s = new(5);
+WriteLine($"Square H: {s.Height}, W: {s.Width}, Area: {s.Area}");
+
+Circle c = new(radius: 2.5);
+WriteLine($"Circle H: {c.Height}, W: {c.Width}, Area: {c.Area}");
\ No newline at end of file
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Rectangle.cs b/vs4win/Chapter06/Ch06Ex02Inheritance/Rectangle.cs
new file mode 100644
index 0000000..ce52432
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Rectangle.cs
@@ -0,0 +1,20 @@
+namespace Packt.Shared;
+
+public class Rectangle : Shape
+{
+ public Rectangle() { }
+
+ public Rectangle(double height, double width)
+ {
+ this.height = height;
+ this.width = width;
+ }
+
+ public override double Area
+ {
+ get
+ {
+ return height * width;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Shape.cs b/vs4win/Chapter06/Ch06Ex02Inheritance/Shape.cs
new file mode 100644
index 0000000..e954c81
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Shape.cs
@@ -0,0 +1,37 @@
+namespace Packt.Shared;
+
+public abstract class Shape
+{
+ // fields
+ protected double height;
+ protected double width;
+
+ // properties
+ public virtual double Height
+ {
+ get
+ {
+ return height;
+ }
+ set
+ {
+ height = value;
+ }
+ }
+
+ public virtual double Width
+ {
+ get
+ {
+ return width;
+ }
+ set
+ {
+ width = value;
+ }
+ }
+
+ // Area must be implemented by derived classes
+ // as a read-only property
+ public abstract double Area { get; }
+}
\ No newline at end of file
diff --git a/vs4win/Chapter06/Ch06Ex02Inheritance/Square.cs b/vs4win/Chapter06/Ch06Ex02Inheritance/Square.cs
new file mode 100644
index 0000000..2b6a755
--- /dev/null
+++ b/vs4win/Chapter06/Ch06Ex02Inheritance/Square.cs
@@ -0,0 +1,26 @@
+namespace Packt.Shared;
+
+public class Square : Rectangle
+{
+ public Square() { }
+
+ public Square(double width) : base(height: width, width: width) { }
+
+ public override double Height
+ {
+ set
+ {
+ height = value;
+ width = value;
+ }
+ }
+
+ public override double Width
+ {
+ set
+ {
+ height = value;
+ width = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vs4win/Chapter06/Chapter06.sln b/vs4win/Chapter06/Chapter06.sln
new file mode 100644
index 0000000..d5411da
--- /dev/null
+++ b/vs4win/Chapter06/Chapter06.sln
@@ -0,0 +1,49 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32210.308
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PacktLibrary", "PacktLibrary\PacktLibrary.csproj", "{6D52FBD2-D3F0-478F-9820-5C5786D4EAC0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PeopleApp", "PeopleApp\PeopleApp.csproj", "{AE82F198-19F8-4AE9-B1C4-2B04D5EE3EEF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NullHandling", "NullHandling\NullHandling.csproj", "{879C7E63-B7FE-4FE4-B3D4-C7CB24C3A73E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeAnalyzing", "CodeAnalyzing\CodeAnalyzing.csproj", "{2E477494-6458-437D-8CB7-A1803A64786C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch06Ex02Inheritance", "Ch06Ex02Inheritance\Ch06Ex02Inheritance.csproj", "{BE4C568B-3904-42DA-8F46-14E0F76E7BED}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6D52FBD2-D3F0-478F-9820-5C5786D4EAC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D52FBD2-D3F0-478F-9820-5C5786D4EAC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D52FBD2-D3F0-478F-9820-5C5786D4EAC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D52FBD2-D3F0-478F-9820-5C5786D4EAC0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AE82F198-19F8-4AE9-B1C4-2B04D5EE3EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AE82F198-19F8-4AE9-B1C4-2B04D5EE3EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AE82F198-19F8-4AE9-B1C4-2B04D5EE3EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AE82F198-19F8-4AE9-B1C4-2B04D5EE3EEF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {879C7E63-B7FE-4FE4-B3D4-C7CB24C3A73E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {879C7E63-B7FE-4FE4-B3D4-C7CB24C3A73E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {879C7E63-B7FE-4FE4-B3D4-C7CB24C3A73E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {879C7E63-B7FE-4FE4-B3D4-C7CB24C3A73E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2E477494-6458-437D-8CB7-A1803A64786C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E477494-6458-437D-8CB7-A1803A64786C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E477494-6458-437D-8CB7-A1803A64786C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E477494-6458-437D-8CB7-A1803A64786C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BE4C568B-3904-42DA-8F46-14E0F76E7BED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE4C568B-3904-42DA-8F46-14E0F76E7BED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE4C568B-3904-42DA-8F46-14E0F76E7BED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE4C568B-3904-42DA-8F46-14E0F76E7BED}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {188D9438-CE6A-4BA3-92E6-3220E788EBD1}
+ EndGlobalSection
+EndGlobal
diff --git a/vs4win/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj b/vs4win/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj
new file mode 100644
index 0000000..a88b122
--- /dev/null
+++ b/vs4win/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj
@@ -0,0 +1,26 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter06/CodeAnalyzing/Program.cs b/vs4win/Chapter06/CodeAnalyzing/Program.cs
new file mode 100644
index 0000000..327333a
--- /dev/null
+++ b/vs4win/Chapter06/CodeAnalyzing/Program.cs
@@ -0,0 +1,23 @@
+//
+// Copyright (c) Packt. All rights reserved.
+//
+namespace CodeAnalyzing;
+
+using System.Diagnostics;
+
+///
+/// The main class for this console app.
+///
+public class Program
+{
+ ///
+ /// The main entry point for this console app.
+ ///
+ ///
+ /// A string array of arguments passed to the console app.
+ ///
+ public static void Main(string[] args)
+ {
+ Debug.WriteLine("Hello, Debugger!");
+ }
+}
diff --git a/vs4win/Chapter06/CodeAnalyzing/stylecop.json b/vs4win/Chapter06/CodeAnalyzing/stylecop.json
new file mode 100644
index 0000000..51d87a8
--- /dev/null
+++ b/vs4win/Chapter06/CodeAnalyzing/stylecop.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "orderingRules": {
+ "usingDirectivesPlacement": "preserve"
+ },
+ "documentationRules": {
+ "companyName": "Packt",
+ "copyrightText": "Copyright (c) Packt. All rights reserved."
+ }
+ }
+}
diff --git a/vs4win/Chapter06/NullHandling/Address.cs b/vs4win/Chapter06/NullHandling/Address.cs
new file mode 100644
index 0000000..25e93f6
--- /dev/null
+++ b/vs4win/Chapter06/NullHandling/Address.cs
@@ -0,0 +1,7 @@
+public class Address
+{
+ public string? Building;
+ public string Street = string.Empty;
+ public string City = string.Empty;
+ public string Region = string.Empty;
+}
diff --git a/vs4win/Chapter06/NullHandling/NullHandling.csproj b/vs4win/Chapter06/NullHandling/NullHandling.csproj
new file mode 100644
index 0000000..6431db6
--- /dev/null
+++ b/vs4win/Chapter06/NullHandling/NullHandling.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter06/NullHandling/Program.cs b/vs4win/Chapter06/NullHandling/Program.cs
new file mode 100644
index 0000000..00ff024
--- /dev/null
+++ b/vs4win/Chapter06/NullHandling/Program.cs
@@ -0,0 +1,29 @@
+int thisCannotBeNull = 4;
+//thisCannotBeNull = null; // compile error!
+WriteLine(thisCannotBeNull);
+
+int? thisCouldBeNull = null;
+
+WriteLine(thisCouldBeNull);
+WriteLine(thisCouldBeNull.GetValueOrDefault());
+
+thisCouldBeNull = 7;
+
+WriteLine(thisCouldBeNull);
+WriteLine(thisCouldBeNull.GetValueOrDefault());
+
+// the actual type of int? is Nullable
+Nullable thisCouldAlsoBeNull = null;
+thisCouldAlsoBeNull = 9;
+WriteLine(thisCouldAlsoBeNull);
+
+// Declaring non-nullable variables and parameters
+
+Address address = new();
+address.Building = null;
+address.Street = null!; // null-forgiving operator
+address.City = "London";
+address.Region = "UK";
+
+WriteLine(address.Building?.Length);
+WriteLine(address.Street.Length);
diff --git a/vs4win/Chapter06/PacktLibrary/DisplacementVector.cs b/vs4win/Chapter06/PacktLibrary/DisplacementVector.cs
new file mode 100644
index 0000000..418ad3b
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/DisplacementVector.cs
@@ -0,0 +1,22 @@
+namespace Packt.Shared;
+
+public struct DisplacementVector
+{
+ public int X { get; set; }
+ public int Y { get; set; }
+
+ public DisplacementVector(int initialX, int initialY)
+ {
+ X = initialX;
+ Y = initialY;
+ }
+
+ public static DisplacementVector operator +(
+ DisplacementVector vector1,
+ DisplacementVector vector2)
+ {
+ return new(
+ vector1.X + vector2.X,
+ vector1.Y + vector2.Y);
+ }
+}
diff --git a/vs4win/Chapter06/PacktLibrary/DvdPlayer.cs b/vs4win/Chapter06/PacktLibrary/DvdPlayer.cs
new file mode 100644
index 0000000..1e33c6b
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/DvdPlayer.cs
@@ -0,0 +1,14 @@
+namespace Packt.Shared;
+
+public class DvdPlayer : IPlayable
+{
+ public void Pause()
+ {
+ WriteLine("DVD player is pausing.");
+ }
+
+ public void Play()
+ {
+ WriteLine("DVD player is playing.");
+ }
+}
diff --git a/vs4win/Chapter06/PacktLibrary/Employee.cs b/vs4win/Chapter06/PacktLibrary/Employee.cs
new file mode 100644
index 0000000..dc1c854
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/Employee.cs
@@ -0,0 +1,22 @@
+namespace Packt.Shared;
+
+public class Employee : Person
+{
+ public string? EmployeeCode { get; set; }
+ public DateTime HireDate { get; set; }
+
+ public new void WriteToConsole()
+ {
+ WriteLine(format:
+ "{0} was born on {1:dd/MM/yy} and hired on {2:dd/MM/yy}",
+ arg0: Name,
+ arg1: DateOfBirth,
+ arg2: HireDate);
+ }
+
+ public override string ToString()
+ {
+ return $"{Name}'s code is {EmployeeCode}";
+ }
+
+}
diff --git a/vs4win/Chapter06/PacktLibrary/IPlayable.cs b/vs4win/Chapter06/PacktLibrary/IPlayable.cs
new file mode 100644
index 0000000..b1b3d50
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/IPlayable.cs
@@ -0,0 +1,11 @@
+namespace Packt.Shared;
+
+public interface IPlayable
+{
+ void Play();
+ void Pause();
+ void Stop() // default interface implementation
+ {
+ WriteLine("Default implementation of Stop.");
+ }
+}
\ No newline at end of file
diff --git a/vs4win/Chapter06/PacktLibrary/PacktLibrary.csproj b/vs4win/Chapter06/PacktLibrary/PacktLibrary.csproj
new file mode 100644
index 0000000..8014967
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/PacktLibrary.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter06/PacktLibrary/Person.cs b/vs4win/Chapter06/PacktLibrary/Person.cs
new file mode 100644
index 0000000..1be2daf
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/Person.cs
@@ -0,0 +1,98 @@
+namespace Packt.Shared;
+
+public class Person : object, IComparable
+{
+ // properties
+ public string? Name { get; set; }
+ public DateTime DateOfBirth { get; set; }
+
+ // methods
+ public void WriteToConsole()
+ {
+ WriteLine($"{Name} was born on a {DateOfBirth:dddd}.");
+ }
+
+ // delegate field
+ public event EventHandler? Shout;
+
+ // data field
+ public int AngerLevel;
+
+ // method
+ public void Poke()
+ {
+ AngerLevel++;
+ if (AngerLevel >= 3)
+ {
+ /*
+ // if something is listening...
+ if (Shout != null)
+ {
+ // ...then call the delegate
+ Shout(this, EventArgs.Empty);
+ }
+ */
+
+ // simplified syntax available in C# 6 or later
+ Shout?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ public int CompareTo(Person? other)
+ {
+ int position;
+ if ((this is not null) && (other is not null))
+ {
+ if ((Name is not null) && (other.Name is not null))
+ {
+ // if both Name values are not null,
+ // use the string implementation of CompareTo
+ position = Name.CompareTo(other.Name);
+ }
+ else if ((Name is not null) && (other.Name is null))
+ {
+ position = -1; // else this Person precedes other Person
+ }
+ else if ((Name is null) && (other.Name is not null))
+ {
+ position = 1; // else this Person follows other Person
+ }
+ else
+ {
+ position = 0; // this Person and other Person are at same position
+ }
+ }
+ else if ((this is not null) && (other is null))
+ {
+ position = -1; // this Person precedes other Person
+ }
+ else if ((this is null) && (other is not null))
+ {
+ position = 1; // this Person follows other Person
+ }
+ else
+ {
+ position = 0; // this Person and other Person are at same position
+ }
+ return position;
+ }
+
+ // overridden methods
+ public override string ToString()
+ {
+ return $"{Name} is a {base.ToString()}";
+ }
+
+ public void TimeTravel(DateTime when)
+ {
+ if (when <= DateOfBirth)
+ {
+ throw new PersonException("If you travel back in time to a date earlier than your own birth, then the universe will explode!");
+ }
+ else
+ {
+ WriteLine($"Welcome to {when:yyyy}!");
+ }
+ }
+
+}
diff --git a/vs4win/Chapter06/PacktLibrary/PersonComparer.cs b/vs4win/Chapter06/PacktLibrary/PersonComparer.cs
new file mode 100644
index 0000000..1232a52
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/PersonComparer.cs
@@ -0,0 +1,56 @@
+namespace Packt.Shared;
+
+public class PersonComparer : IComparer
+{
+ public int Compare(Person? x, Person? y)
+ {
+ int position;
+ if ((x is not null) && (y is not null))
+ {
+ if ((x.Name is not null) && (y.Name is not null))
+ {
+ // if both Name values are not null...
+
+ // ...compare the Name lengths...
+ int result = x.Name.Length.CompareTo(y.Name.Length);
+
+ /// ...if they are equal...
+ if (result == 0)
+ {
+ // ...then compare by the Names...
+ return x.Name.CompareTo(y.Name);
+ }
+ else
+ {
+ // ...otherwise compare by the lengths.
+ position = result;
+ }
+ }
+ else if ((x.Name is not null) && (y.Name is null))
+ {
+ position = -1; // else x Person precedes y Person
+ }
+ else if ((x.Name is null) && (y.Name is not null))
+ {
+ position = 1; // else x Person follows y Person
+ }
+ else
+ {
+ position = 0; // x Person and y Person are at same position
+ }
+ }
+ else if ((x is not null) && (y is null))
+ {
+ position = -1; // x Person precedes y Person
+ }
+ else if ((x is null) && (y is not null))
+ {
+ position = 1; // x Person follows y Person
+ }
+ else
+ {
+ position = 0; // x Person and y Person are at same position
+ }
+ return position;
+ }
+}
diff --git a/vs4win/Chapter06/PacktLibrary/PersonException.cs b/vs4win/Chapter06/PacktLibrary/PersonException.cs
new file mode 100644
index 0000000..36788f7
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/PersonException.cs
@@ -0,0 +1,11 @@
+namespace Packt.Shared;
+
+public class PersonException : Exception
+{
+ public PersonException() : base() { }
+
+ public PersonException(string message) : base(message) { }
+
+ public PersonException(string message, Exception innerException)
+ : base(message, innerException) { }
+}
diff --git a/vs4win/Chapter06/PacktLibrary/StringExtensions.cs b/vs4win/Chapter06/PacktLibrary/StringExtensions.cs
new file mode 100644
index 0000000..75f4b6a
--- /dev/null
+++ b/vs4win/Chapter06/PacktLibrary/StringExtensions.cs
@@ -0,0 +1,15 @@
+using System.Text.RegularExpressions; // to get Regex
+
+namespace Packt.Shared;
+
+public static class StringExtensions
+{
+ public static bool IsValidEmail(this string input)
+ {
+ // use a simple regular expression to check
+ // that the input string is a valid email
+
+ return Regex.IsMatch(input,
+ @"[a-zA-Z0-9\.-_]+@[a-zA-Z0-9\.-_]+");
+ }
+}
diff --git a/vs4win/Chapter06/PeopleApp/PeopleApp.csproj b/vs4win/Chapter06/PeopleApp/PeopleApp.csproj
new file mode 100644
index 0000000..3ba995a
--- /dev/null
+++ b/vs4win/Chapter06/PeopleApp/PeopleApp.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vs4win/Chapter06/PeopleApp/Program.EventHandlers.cs b/vs4win/Chapter06/PeopleApp/Program.EventHandlers.cs
new file mode 100644
index 0000000..38a9440
--- /dev/null
+++ b/vs4win/Chapter06/PeopleApp/Program.EventHandlers.cs
@@ -0,0 +1,24 @@
+using Packt.Shared;
+
+partial class Program
+{
+ // a method to handle the Shout event received by the harry object
+ static void Harry_Shout(object? sender, EventArgs e)
+ {
+ if (sender is null) return;
+ Person? p = sender as Person;
+ if (p is null) return;
+
+ WriteLine($"{p.Name} is this angry: {p.AngerLevel}.");
+ }
+
+ // another method to handle the Shout event received by the harry object
+ static void Harry_Shout2(object? sender, EventArgs e)
+ {
+ if (sender is null) return;
+ Person? p = sender as Person;
+ if (p is null) return;
+
+ WriteLine($"Stop it!");
+ }
+}
diff --git a/vs4win/Chapter06/PeopleApp/Program.Helpers.cs b/vs4win/Chapter06/PeopleApp/Program.Helpers.cs
new file mode 100644
index 0000000..2323a52
--- /dev/null
+++ b/vs4win/Chapter06/PeopleApp/Program.Helpers.cs
@@ -0,0 +1,19 @@
+using Packt.Shared;
+
+partial class Program
+{
+ static void OutputPeopleNames(IEnumerable people, string title)
+ {
+ WriteLine(title);
+ foreach (Person? p in people)
+ {
+ WriteLine(" {0}",
+ p is null ? " Person" : p.Name ?? " Name");
+
+
+ /* if p is null then output: Person
+ else output: p.Name
+ unless p.Name is null in which case output: Name */
+ }
+ }
+}
diff --git a/vs4win/Chapter06/PeopleApp/Program.cs b/vs4win/Chapter06/PeopleApp/Program.cs
new file mode 100644
index 0000000..1dcfe6a
--- /dev/null
+++ b/vs4win/Chapter06/PeopleApp/Program.cs
@@ -0,0 +1,184 @@
+using Packt.Shared;
+
+Person harry = new()
+{
+ Name = "Harry",
+ DateOfBirth = new(year: 2001, month: 3, day: 25)
+};
+
+harry.WriteToConsole();
+
+// non-generic lookup collection
+System.Collections.Hashtable lookupObject = new();
+lookupObject.Add(key: 1, value: "Alpha");
+lookupObject.Add(key: 2, value: "Beta");
+lookupObject.Add(key: 3, value: "Gamma");
+lookupObject.Add(key: harry, value: "Delta");
+
+int key = 2; // lookup the value that has 2 as its key
+
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: key,
+ arg1: lookupObject[key]);
+
+// lookup the value that has harry as its key
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: harry,
+ arg1: lookupObject[harry]);
+
+// generic lookup collection
+Dictionary lookupIntString = new();
+lookupIntString.Add(key: 1, value: "Alpha");
+lookupIntString.Add(key: 2, value: "Beta");
+lookupIntString.Add(key: 3, value: "Gamma");
+lookupIntString.Add(key: 4, value: "Delta");
+
+key = 3;
+
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: key,
+ arg1: lookupIntString[key]);
+
+// Defining and handling delegates
+
+// assign event handler methods to Shout event
+harry.Shout += Harry_Shout;
+harry.Shout += Harry_Shout2;
+
+// call the Poke method that raises the Shout event
+harry.Poke();
+harry.Poke();
+harry.Poke();
+harry.Poke();
+
+// Comparing objects when sorting
+
+Person?[] people =
+{
+ null,
+ new() { Name = "Simon" },
+ new() { Name = "Jenny" },
+ new() { Name = "Adam" },
+ new() { Name = null },
+ new() { Name = "Richard" }
+};
+
+OutputPeopleNames(people, "Initial list of people:");
+
+Array.Sort(people);
+
+OutputPeopleNames(people,
+ "After sorting using Person's IComparable implementation:");
+
+Array.Sort(people, new PersonComparer());
+
+OutputPeopleNames(people,
+ "After sorting using PersonComparer's IComparer implementation:");
+
+// Equality of types
+
+int a = 3;
+int b = 3;
+WriteLine($"a: {a}, b: {b}");
+WriteLine($"a == b: {(a == b)}");
+
+Person p1 = new() { Name = "Kevin" };
+Person p2 = new() { Name = "Kevin" };
+WriteLine($"p1: {p1}, p2: {p2}");
+WriteLine($"p1 == p2: {(p1 == p2)}");
+
+Person p3 = p1;
+WriteLine($"p3: {p3}");
+WriteLine($"p1 == p3: {(p1 == p3)}");
+
+WriteLine($"p1.Name: {p1.Name}, p2.Name: {p2.Name}");
+WriteLine($"p1.Name == p2.Name: {(p1.Name == p2.Name)}");
+
+// Defining struct types
+
+DisplacementVector dv1 = new(3, 5);
+DisplacementVector dv2 = new(-2, 7);
+DisplacementVector dv3 = dv1 + dv2;
+WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X}, {dv3.Y})");
+
+DisplacementVector dv4 = new();
+WriteLine($"({dv4.X}, {dv4.Y})");
+
+// Inheriting from classes
+
+Employee john = new()
+{
+ Name = "John Jones",
+ DateOfBirth = new(year: 1990, month: 7, day: 28)
+};
+john.WriteToConsole();
+
+john.EmployeeCode = "JJ001";
+john.HireDate = new(year: 2014, month: 11, day: 23);
+WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yy}");
+
+WriteLine(john.ToString());
+
+Employee aliceInEmployee = new()
+{ 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;
+
+ // safely do something with explicitAlice
+}
+
+/* alternative syntax
+if (aliceInPerson is Employee explicitAlice)
+{
+ WriteLine($"{nameof(aliceInPerson)} IS an Employee");
+ // safely do something with explicitAlice
+}
+ */
+
+Employee? aliceAsEmployee = aliceInPerson as Employee; // could be null
+
+if (aliceAsEmployee is not null)
+{
+ WriteLine($"{nameof(aliceInPerson)} AS an Employee");
+
+ // safely do something with aliceAsEmployee
+}
+
+try
+{
+ john.TimeTravel(when: new(1999, 12, 31));
+ john.TimeTravel(when: new(1950, 12, 25));
+}
+catch (PersonException ex)
+{
+ WriteLine(ex.Message);
+}
+
+string email1 = "pamela@test.com";
+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());
diff --git a/vscode/Chapter05/Chapter05.code-workspace b/vscode/Chapter05/Chapter05.code-workspace
index 9866d2f..05d45eb 100644
--- a/vscode/Chapter05/Chapter05.code-workspace
+++ b/vscode/Chapter05/Chapter05.code-workspace
@@ -5,6 +5,9 @@
},
{
"path": "PeopleApp"
+ },
+ {
+ "path": "Namespaces"
}
]
}
\ No newline at end of file
diff --git a/vscode/Chapter05/Namespaces/France.Paris.cs b/vscode/Chapter05/Namespaces/France.Paris.cs
new file mode 100644
index 0000000..af7e47d
--- /dev/null
+++ b/vscode/Chapter05/Namespaces/France.Paris.cs
@@ -0,0 +1,6 @@
+namespace France
+{
+ public class Paris
+ {
+ }
+}
diff --git a/vscode/Chapter05/Namespaces/Namespaces.csproj b/vscode/Chapter05/Namespaces/Namespaces.csproj
new file mode 100644
index 0000000..cd63b28
--- /dev/null
+++ b/vscode/Chapter05/Namespaces/Namespaces.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vscode/Chapter05/Namespaces/Program.cs b/vscode/Chapter05/Namespaces/Program.cs
new file mode 100644
index 0000000..f5b80fb
--- /dev/null
+++ b/vscode/Chapter05/Namespaces/Program.cs
@@ -0,0 +1,10 @@
+using France;
+using us = Texas; // us becomes alias for the namespace and it is not imported
+using Env = System.Environment;
+
+Paris p1 = new();
+us.Paris p2 = new();
+
+WriteLine(Env.OSVersion);
+WriteLine(Env.MachineName);
+WriteLine(Env.CurrentDirectory);
\ No newline at end of file
diff --git a/vscode/Chapter05/Namespaces/Texas.Paris.cs b/vscode/Chapter05/Namespaces/Texas.Paris.cs
new file mode 100644
index 0000000..9ece88d
--- /dev/null
+++ b/vscode/Chapter05/Namespaces/Texas.Paris.cs
@@ -0,0 +1,6 @@
+namespace Texas
+{
+ public class Paris
+ {
+ }
+}
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj b/vscode/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj
new file mode 100644
index 0000000..cd63b28
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Circle.cs b/vscode/Chapter06/Ch06Ex02Inheritance/Circle.cs
new file mode 100644
index 0000000..861431c
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Circle.cs
@@ -0,0 +1,29 @@
+namespace Packt.Shared;
+
+public class Circle : Square
+{
+ public Circle() { }
+
+ public Circle(double radius) : base(width: radius * 2) { }
+
+ public double Radius
+ {
+ get
+ {
+ return height / 2;
+ }
+ set
+ {
+ Height = value * 2;
+ }
+ }
+
+ public override double Area
+ {
+ get
+ {
+ double radius = height / 2;
+ return Math.PI * radius * radius;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Program.cs b/vscode/Chapter06/Ch06Ex02Inheritance/Program.cs
new file mode 100644
index 0000000..5558cfe
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Program.cs
@@ -0,0 +1,10 @@
+using Packt.Shared;
+
+Rectangle r = new(height: 3, width: 4.5);
+WriteLine($"Rectangle H: {r.Height}, W: {r.Width}, Area: {r.Area}");
+
+Square s = new(5);
+WriteLine($"Square H: {s.Height}, W: {s.Width}, Area: {s.Area}");
+
+Circle c = new(radius: 2.5);
+WriteLine($"Circle H: {c.Height}, W: {c.Width}, Area: {c.Area}");
\ No newline at end of file
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Rectangle.cs b/vscode/Chapter06/Ch06Ex02Inheritance/Rectangle.cs
new file mode 100644
index 0000000..ce52432
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Rectangle.cs
@@ -0,0 +1,20 @@
+namespace Packt.Shared;
+
+public class Rectangle : Shape
+{
+ public Rectangle() { }
+
+ public Rectangle(double height, double width)
+ {
+ this.height = height;
+ this.width = width;
+ }
+
+ public override double Area
+ {
+ get
+ {
+ return height * width;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Shape.cs b/vscode/Chapter06/Ch06Ex02Inheritance/Shape.cs
new file mode 100644
index 0000000..e954c81
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Shape.cs
@@ -0,0 +1,37 @@
+namespace Packt.Shared;
+
+public abstract class Shape
+{
+ // fields
+ protected double height;
+ protected double width;
+
+ // properties
+ public virtual double Height
+ {
+ get
+ {
+ return height;
+ }
+ set
+ {
+ height = value;
+ }
+ }
+
+ public virtual double Width
+ {
+ get
+ {
+ return width;
+ }
+ set
+ {
+ width = value;
+ }
+ }
+
+ // Area must be implemented by derived classes
+ // as a read-only property
+ public abstract double Area { get; }
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/Ch06Ex02Inheritance/Square.cs b/vscode/Chapter06/Ch06Ex02Inheritance/Square.cs
new file mode 100644
index 0000000..2b6a755
--- /dev/null
+++ b/vscode/Chapter06/Ch06Ex02Inheritance/Square.cs
@@ -0,0 +1,26 @@
+namespace Packt.Shared;
+
+public class Square : Rectangle
+{
+ public Square() { }
+
+ public Square(double width) : base(height: width, width: width) { }
+
+ public override double Height
+ {
+ set
+ {
+ height = value;
+ width = value;
+ }
+ }
+
+ public override double Width
+ {
+ set
+ {
+ height = value;
+ width = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/Chapter06.code-workspace b/vscode/Chapter06/Chapter06.code-workspace
new file mode 100644
index 0000000..2ddc5b7
--- /dev/null
+++ b/vscode/Chapter06/Chapter06.code-workspace
@@ -0,0 +1,19 @@
+{
+ "folders": [
+ {
+ "path": "PacktLibrary"
+ },
+ {
+ "path": "PeopleApp"
+ },
+ {
+ "path": "NullHandling"
+ },
+ {
+ "path": "CodeAnalyzing"
+ },
+ {
+ "path": "Ch06Ex02Inheritance"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj b/vscode/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj
new file mode 100644
index 0000000..a88b122
--- /dev/null
+++ b/vscode/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj
@@ -0,0 +1,26 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vscode/Chapter06/CodeAnalyzing/Program.cs b/vscode/Chapter06/CodeAnalyzing/Program.cs
new file mode 100644
index 0000000..327333a
--- /dev/null
+++ b/vscode/Chapter06/CodeAnalyzing/Program.cs
@@ -0,0 +1,23 @@
+//
+// Copyright (c) Packt. All rights reserved.
+//
+namespace CodeAnalyzing;
+
+using System.Diagnostics;
+
+///
+/// The main class for this console app.
+///
+public class Program
+{
+ ///
+ /// The main entry point for this console app.
+ ///
+ ///
+ /// A string array of arguments passed to the console app.
+ ///
+ public static void Main(string[] args)
+ {
+ Debug.WriteLine("Hello, Debugger!");
+ }
+}
diff --git a/vscode/Chapter06/CodeAnalyzing/stylecop.json b/vscode/Chapter06/CodeAnalyzing/stylecop.json
new file mode 100644
index 0000000..51d87a8
--- /dev/null
+++ b/vscode/Chapter06/CodeAnalyzing/stylecop.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "orderingRules": {
+ "usingDirectivesPlacement": "preserve"
+ },
+ "documentationRules": {
+ "companyName": "Packt",
+ "copyrightText": "Copyright (c) Packt. All rights reserved."
+ }
+ }
+}
diff --git a/vscode/Chapter06/NullHandling/Address.cs b/vscode/Chapter06/NullHandling/Address.cs
new file mode 100644
index 0000000..25e93f6
--- /dev/null
+++ b/vscode/Chapter06/NullHandling/Address.cs
@@ -0,0 +1,7 @@
+public class Address
+{
+ public string? Building;
+ public string Street = string.Empty;
+ public string City = string.Empty;
+ public string Region = string.Empty;
+}
diff --git a/vscode/Chapter06/NullHandling/NullHandling.csproj b/vscode/Chapter06/NullHandling/NullHandling.csproj
new file mode 100644
index 0000000..6431db6
--- /dev/null
+++ b/vscode/Chapter06/NullHandling/NullHandling.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vscode/Chapter06/NullHandling/Program.cs b/vscode/Chapter06/NullHandling/Program.cs
new file mode 100644
index 0000000..00ff024
--- /dev/null
+++ b/vscode/Chapter06/NullHandling/Program.cs
@@ -0,0 +1,29 @@
+int thisCannotBeNull = 4;
+//thisCannotBeNull = null; // compile error!
+WriteLine(thisCannotBeNull);
+
+int? thisCouldBeNull = null;
+
+WriteLine(thisCouldBeNull);
+WriteLine(thisCouldBeNull.GetValueOrDefault());
+
+thisCouldBeNull = 7;
+
+WriteLine(thisCouldBeNull);
+WriteLine(thisCouldBeNull.GetValueOrDefault());
+
+// the actual type of int? is Nullable
+Nullable thisCouldAlsoBeNull = null;
+thisCouldAlsoBeNull = 9;
+WriteLine(thisCouldAlsoBeNull);
+
+// Declaring non-nullable variables and parameters
+
+Address address = new();
+address.Building = null;
+address.Street = null!; // null-forgiving operator
+address.City = "London";
+address.Region = "UK";
+
+WriteLine(address.Building?.Length);
+WriteLine(address.Street.Length);
diff --git a/vscode/Chapter06/PacktLibrary/DisplacementVector.cs b/vscode/Chapter06/PacktLibrary/DisplacementVector.cs
new file mode 100644
index 0000000..418ad3b
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/DisplacementVector.cs
@@ -0,0 +1,22 @@
+namespace Packt.Shared;
+
+public struct DisplacementVector
+{
+ public int X { get; set; }
+ public int Y { get; set; }
+
+ public DisplacementVector(int initialX, int initialY)
+ {
+ X = initialX;
+ Y = initialY;
+ }
+
+ public static DisplacementVector operator +(
+ DisplacementVector vector1,
+ DisplacementVector vector2)
+ {
+ return new(
+ vector1.X + vector2.X,
+ vector1.Y + vector2.Y);
+ }
+}
diff --git a/vscode/Chapter06/PacktLibrary/DvdPlayer.cs b/vscode/Chapter06/PacktLibrary/DvdPlayer.cs
new file mode 100644
index 0000000..1e33c6b
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/DvdPlayer.cs
@@ -0,0 +1,14 @@
+namespace Packt.Shared;
+
+public class DvdPlayer : IPlayable
+{
+ public void Pause()
+ {
+ WriteLine("DVD player is pausing.");
+ }
+
+ public void Play()
+ {
+ WriteLine("DVD player is playing.");
+ }
+}
diff --git a/vscode/Chapter06/PacktLibrary/Employee.cs b/vscode/Chapter06/PacktLibrary/Employee.cs
new file mode 100644
index 0000000..dc1c854
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/Employee.cs
@@ -0,0 +1,22 @@
+namespace Packt.Shared;
+
+public class Employee : Person
+{
+ public string? EmployeeCode { get; set; }
+ public DateTime HireDate { get; set; }
+
+ public new void WriteToConsole()
+ {
+ WriteLine(format:
+ "{0} was born on {1:dd/MM/yy} and hired on {2:dd/MM/yy}",
+ arg0: Name,
+ arg1: DateOfBirth,
+ arg2: HireDate);
+ }
+
+ public override string ToString()
+ {
+ return $"{Name}'s code is {EmployeeCode}";
+ }
+
+}
diff --git a/vscode/Chapter06/PacktLibrary/IPlayable.cs b/vscode/Chapter06/PacktLibrary/IPlayable.cs
new file mode 100644
index 0000000..b1b3d50
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/IPlayable.cs
@@ -0,0 +1,11 @@
+namespace Packt.Shared;
+
+public interface IPlayable
+{
+ void Play();
+ void Pause();
+ void Stop() // default interface implementation
+ {
+ WriteLine("Default implementation of Stop.");
+ }
+}
\ No newline at end of file
diff --git a/vscode/Chapter06/PacktLibrary/PacktLibrary.csproj b/vscode/Chapter06/PacktLibrary/PacktLibrary.csproj
new file mode 100644
index 0000000..8014967
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/PacktLibrary.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/vscode/Chapter06/PacktLibrary/Person.cs b/vscode/Chapter06/PacktLibrary/Person.cs
new file mode 100644
index 0000000..1be2daf
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/Person.cs
@@ -0,0 +1,98 @@
+namespace Packt.Shared;
+
+public class Person : object, IComparable
+{
+ // properties
+ public string? Name { get; set; }
+ public DateTime DateOfBirth { get; set; }
+
+ // methods
+ public void WriteToConsole()
+ {
+ WriteLine($"{Name} was born on a {DateOfBirth:dddd}.");
+ }
+
+ // delegate field
+ public event EventHandler? Shout;
+
+ // data field
+ public int AngerLevel;
+
+ // method
+ public void Poke()
+ {
+ AngerLevel++;
+ if (AngerLevel >= 3)
+ {
+ /*
+ // if something is listening...
+ if (Shout != null)
+ {
+ // ...then call the delegate
+ Shout(this, EventArgs.Empty);
+ }
+ */
+
+ // simplified syntax available in C# 6 or later
+ Shout?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ public int CompareTo(Person? other)
+ {
+ int position;
+ if ((this is not null) && (other is not null))
+ {
+ if ((Name is not null) && (other.Name is not null))
+ {
+ // if both Name values are not null,
+ // use the string implementation of CompareTo
+ position = Name.CompareTo(other.Name);
+ }
+ else if ((Name is not null) && (other.Name is null))
+ {
+ position = -1; // else this Person precedes other Person
+ }
+ else if ((Name is null) && (other.Name is not null))
+ {
+ position = 1; // else this Person follows other Person
+ }
+ else
+ {
+ position = 0; // this Person and other Person are at same position
+ }
+ }
+ else if ((this is not null) && (other is null))
+ {
+ position = -1; // this Person precedes other Person
+ }
+ else if ((this is null) && (other is not null))
+ {
+ position = 1; // this Person follows other Person
+ }
+ else
+ {
+ position = 0; // this Person and other Person are at same position
+ }
+ return position;
+ }
+
+ // overridden methods
+ public override string ToString()
+ {
+ return $"{Name} is a {base.ToString()}";
+ }
+
+ public void TimeTravel(DateTime when)
+ {
+ if (when <= DateOfBirth)
+ {
+ throw new PersonException("If you travel back in time to a date earlier than your own birth, then the universe will explode!");
+ }
+ else
+ {
+ WriteLine($"Welcome to {when:yyyy}!");
+ }
+ }
+
+}
diff --git a/vscode/Chapter06/PacktLibrary/PersonComparer.cs b/vscode/Chapter06/PacktLibrary/PersonComparer.cs
new file mode 100644
index 0000000..1232a52
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/PersonComparer.cs
@@ -0,0 +1,56 @@
+namespace Packt.Shared;
+
+public class PersonComparer : IComparer
+{
+ public int Compare(Person? x, Person? y)
+ {
+ int position;
+ if ((x is not null) && (y is not null))
+ {
+ if ((x.Name is not null) && (y.Name is not null))
+ {
+ // if both Name values are not null...
+
+ // ...compare the Name lengths...
+ int result = x.Name.Length.CompareTo(y.Name.Length);
+
+ /// ...if they are equal...
+ if (result == 0)
+ {
+ // ...then compare by the Names...
+ return x.Name.CompareTo(y.Name);
+ }
+ else
+ {
+ // ...otherwise compare by the lengths.
+ position = result;
+ }
+ }
+ else if ((x.Name is not null) && (y.Name is null))
+ {
+ position = -1; // else x Person precedes y Person
+ }
+ else if ((x.Name is null) && (y.Name is not null))
+ {
+ position = 1; // else x Person follows y Person
+ }
+ else
+ {
+ position = 0; // x Person and y Person are at same position
+ }
+ }
+ else if ((x is not null) && (y is null))
+ {
+ position = -1; // x Person precedes y Person
+ }
+ else if ((x is null) && (y is not null))
+ {
+ position = 1; // x Person follows y Person
+ }
+ else
+ {
+ position = 0; // x Person and y Person are at same position
+ }
+ return position;
+ }
+}
diff --git a/vscode/Chapter06/PacktLibrary/PersonException.cs b/vscode/Chapter06/PacktLibrary/PersonException.cs
new file mode 100644
index 0000000..36788f7
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/PersonException.cs
@@ -0,0 +1,11 @@
+namespace Packt.Shared;
+
+public class PersonException : Exception
+{
+ public PersonException() : base() { }
+
+ public PersonException(string message) : base(message) { }
+
+ public PersonException(string message, Exception innerException)
+ : base(message, innerException) { }
+}
diff --git a/vscode/Chapter06/PacktLibrary/StringExtensions.cs b/vscode/Chapter06/PacktLibrary/StringExtensions.cs
new file mode 100644
index 0000000..75f4b6a
--- /dev/null
+++ b/vscode/Chapter06/PacktLibrary/StringExtensions.cs
@@ -0,0 +1,15 @@
+using System.Text.RegularExpressions; // to get Regex
+
+namespace Packt.Shared;
+
+public static class StringExtensions
+{
+ public static bool IsValidEmail(this string input)
+ {
+ // use a simple regular expression to check
+ // that the input string is a valid email
+
+ return Regex.IsMatch(input,
+ @"[a-zA-Z0-9\.-_]+@[a-zA-Z0-9\.-_]+");
+ }
+}
diff --git a/vscode/Chapter06/PeopleApp/PeopleApp.csproj b/vscode/Chapter06/PeopleApp/PeopleApp.csproj
new file mode 100644
index 0000000..3ba995a
--- /dev/null
+++ b/vscode/Chapter06/PeopleApp/PeopleApp.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vscode/Chapter06/PeopleApp/Program.EventHandlers.cs b/vscode/Chapter06/PeopleApp/Program.EventHandlers.cs
new file mode 100644
index 0000000..38a9440
--- /dev/null
+++ b/vscode/Chapter06/PeopleApp/Program.EventHandlers.cs
@@ -0,0 +1,24 @@
+using Packt.Shared;
+
+partial class Program
+{
+ // a method to handle the Shout event received by the harry object
+ static void Harry_Shout(object? sender, EventArgs e)
+ {
+ if (sender is null) return;
+ Person? p = sender as Person;
+ if (p is null) return;
+
+ WriteLine($"{p.Name} is this angry: {p.AngerLevel}.");
+ }
+
+ // another method to handle the Shout event received by the harry object
+ static void Harry_Shout2(object? sender, EventArgs e)
+ {
+ if (sender is null) return;
+ Person? p = sender as Person;
+ if (p is null) return;
+
+ WriteLine($"Stop it!");
+ }
+}
diff --git a/vscode/Chapter06/PeopleApp/Program.Helpers.cs b/vscode/Chapter06/PeopleApp/Program.Helpers.cs
new file mode 100644
index 0000000..2323a52
--- /dev/null
+++ b/vscode/Chapter06/PeopleApp/Program.Helpers.cs
@@ -0,0 +1,19 @@
+using Packt.Shared;
+
+partial class Program
+{
+ static void OutputPeopleNames(IEnumerable people, string title)
+ {
+ WriteLine(title);
+ foreach (Person? p in people)
+ {
+ WriteLine(" {0}",
+ p is null ? " Person" : p.Name ?? " Name");
+
+
+ /* if p is null then output: Person
+ else output: p.Name
+ unless p.Name is null in which case output: Name */
+ }
+ }
+}
diff --git a/vscode/Chapter06/PeopleApp/Program.cs b/vscode/Chapter06/PeopleApp/Program.cs
new file mode 100644
index 0000000..1dcfe6a
--- /dev/null
+++ b/vscode/Chapter06/PeopleApp/Program.cs
@@ -0,0 +1,184 @@
+using Packt.Shared;
+
+Person harry = new()
+{
+ Name = "Harry",
+ DateOfBirth = new(year: 2001, month: 3, day: 25)
+};
+
+harry.WriteToConsole();
+
+// non-generic lookup collection
+System.Collections.Hashtable lookupObject = new();
+lookupObject.Add(key: 1, value: "Alpha");
+lookupObject.Add(key: 2, value: "Beta");
+lookupObject.Add(key: 3, value: "Gamma");
+lookupObject.Add(key: harry, value: "Delta");
+
+int key = 2; // lookup the value that has 2 as its key
+
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: key,
+ arg1: lookupObject[key]);
+
+// lookup the value that has harry as its key
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: harry,
+ arg1: lookupObject[harry]);
+
+// generic lookup collection
+Dictionary lookupIntString = new();
+lookupIntString.Add(key: 1, value: "Alpha");
+lookupIntString.Add(key: 2, value: "Beta");
+lookupIntString.Add(key: 3, value: "Gamma");
+lookupIntString.Add(key: 4, value: "Delta");
+
+key = 3;
+
+WriteLine(format: "Key {0} has value: {1}",
+ arg0: key,
+ arg1: lookupIntString[key]);
+
+// Defining and handling delegates
+
+// assign event handler methods to Shout event
+harry.Shout += Harry_Shout;
+harry.Shout += Harry_Shout2;
+
+// call the Poke method that raises the Shout event
+harry.Poke();
+harry.Poke();
+harry.Poke();
+harry.Poke();
+
+// Comparing objects when sorting
+
+Person?[] people =
+{
+ null,
+ new() { Name = "Simon" },
+ new() { Name = "Jenny" },
+ new() { Name = "Adam" },
+ new() { Name = null },
+ new() { Name = "Richard" }
+};
+
+OutputPeopleNames(people, "Initial list of people:");
+
+Array.Sort(people);
+
+OutputPeopleNames(people,
+ "After sorting using Person's IComparable implementation:");
+
+Array.Sort(people, new PersonComparer());
+
+OutputPeopleNames(people,
+ "After sorting using PersonComparer's IComparer implementation:");
+
+// Equality of types
+
+int a = 3;
+int b = 3;
+WriteLine($"a: {a}, b: {b}");
+WriteLine($"a == b: {(a == b)}");
+
+Person p1 = new() { Name = "Kevin" };
+Person p2 = new() { Name = "Kevin" };
+WriteLine($"p1: {p1}, p2: {p2}");
+WriteLine($"p1 == p2: {(p1 == p2)}");
+
+Person p3 = p1;
+WriteLine($"p3: {p3}");
+WriteLine($"p1 == p3: {(p1 == p3)}");
+
+WriteLine($"p1.Name: {p1.Name}, p2.Name: {p2.Name}");
+WriteLine($"p1.Name == p2.Name: {(p1.Name == p2.Name)}");
+
+// Defining struct types
+
+DisplacementVector dv1 = new(3, 5);
+DisplacementVector dv2 = new(-2, 7);
+DisplacementVector dv3 = dv1 + dv2;
+WriteLine($"({dv1.X}, {dv1.Y}) + ({dv2.X}, {dv2.Y}) = ({dv3.X}, {dv3.Y})");
+
+DisplacementVector dv4 = new();
+WriteLine($"({dv4.X}, {dv4.Y})");
+
+// Inheriting from classes
+
+Employee john = new()
+{
+ Name = "John Jones",
+ DateOfBirth = new(year: 1990, month: 7, day: 28)
+};
+john.WriteToConsole();
+
+john.EmployeeCode = "JJ001";
+john.HireDate = new(year: 2014, month: 11, day: 23);
+WriteLine($"{john.Name} was hired on {john.HireDate:dd/MM/yy}");
+
+WriteLine(john.ToString());
+
+Employee aliceInEmployee = new()
+{ 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;
+
+ // safely do something with explicitAlice
+}
+
+/* alternative syntax
+if (aliceInPerson is Employee explicitAlice)
+{
+ WriteLine($"{nameof(aliceInPerson)} IS an Employee");
+ // safely do something with explicitAlice
+}
+ */
+
+Employee? aliceAsEmployee = aliceInPerson as Employee; // could be null
+
+if (aliceAsEmployee is not null)
+{
+ WriteLine($"{nameof(aliceInPerson)} AS an Employee");
+
+ // safely do something with aliceAsEmployee
+}
+
+try
+{
+ john.TimeTravel(when: new(1999, 12, 31));
+ john.TimeTravel(when: new(1950, 12, 25));
+}
+catch (PersonException ex)
+{
+ WriteLine(ex.Message);
+}
+
+string email1 = "pamela@test.com";
+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());