From 18f89e91d46f89e51a86e647dd50b82a030020e6 Mon Sep 17 00:00:00 2001 From: Mark J Price Date: Sun, 27 Feb 2022 19:08:52 +0000 Subject: [PATCH] Initial commit --- vs4win/Chapter05/Chapter05.sln | 10 +- vs4win/Chapter05/Namespaces/France.Paris.cs | 6 + vs4win/Chapter05/Namespaces/Namespaces.csproj | 14 ++ vs4win/Chapter05/Namespaces/Program.cs | 10 + vs4win/Chapter05/Namespaces/Texas.Paris.cs | 6 + .../Ch06Ex02Inheritance.csproj | 14 ++ .../Chapter06/Ch06Ex02Inheritance/Circle.cs | 29 +++ .../Chapter06/Ch06Ex02Inheritance/Program.cs | 10 + .../Ch06Ex02Inheritance/Rectangle.cs | 20 ++ vs4win/Chapter06/Ch06Ex02Inheritance/Shape.cs | 37 ++++ .../Chapter06/Ch06Ex02Inheritance/Square.cs | 26 +++ vs4win/Chapter06/Chapter06.sln | 49 +++++ .../CodeAnalyzing/CodeAnalyzing.csproj | 26 +++ vs4win/Chapter06/CodeAnalyzing/Program.cs | 23 +++ vs4win/Chapter06/CodeAnalyzing/stylecop.json | 12 ++ vs4win/Chapter06/NullHandling/Address.cs | 7 + .../NullHandling/NullHandling.csproj | 14 ++ vs4win/Chapter06/NullHandling/Program.cs | 29 +++ .../PacktLibrary/DisplacementVector.cs | 22 +++ vs4win/Chapter06/PacktLibrary/DvdPlayer.cs | 14 ++ vs4win/Chapter06/PacktLibrary/Employee.cs | 22 +++ vs4win/Chapter06/PacktLibrary/IPlayable.cs | 11 ++ .../PacktLibrary/PacktLibrary.csproj | 13 ++ vs4win/Chapter06/PacktLibrary/Person.cs | 98 ++++++++++ .../Chapter06/PacktLibrary/PersonComparer.cs | 56 ++++++ .../Chapter06/PacktLibrary/PersonException.cs | 11 ++ .../PacktLibrary/StringExtensions.cs | 15 ++ vs4win/Chapter06/PeopleApp/PeopleApp.csproj | 19 ++ .../PeopleApp/Program.EventHandlers.cs | 24 +++ vs4win/Chapter06/PeopleApp/Program.Helpers.cs | 19 ++ vs4win/Chapter06/PeopleApp/Program.cs | 184 ++++++++++++++++++ vscode/Chapter05/Chapter05.code-workspace | 3 + vscode/Chapter05/Namespaces/France.Paris.cs | 6 + vscode/Chapter05/Namespaces/Namespaces.csproj | 14 ++ vscode/Chapter05/Namespaces/Program.cs | 10 + vscode/Chapter05/Namespaces/Texas.Paris.cs | 6 + .../Ch06Ex02Inheritance.csproj | 14 ++ .../Chapter06/Ch06Ex02Inheritance/Circle.cs | 29 +++ .../Chapter06/Ch06Ex02Inheritance/Program.cs | 10 + .../Ch06Ex02Inheritance/Rectangle.cs | 20 ++ vscode/Chapter06/Ch06Ex02Inheritance/Shape.cs | 37 ++++ .../Chapter06/Ch06Ex02Inheritance/Square.cs | 26 +++ vscode/Chapter06/Chapter06.code-workspace | 19 ++ .../CodeAnalyzing/CodeAnalyzing.csproj | 26 +++ vscode/Chapter06/CodeAnalyzing/Program.cs | 23 +++ vscode/Chapter06/CodeAnalyzing/stylecop.json | 12 ++ vscode/Chapter06/NullHandling/Address.cs | 7 + .../NullHandling/NullHandling.csproj | 14 ++ vscode/Chapter06/NullHandling/Program.cs | 29 +++ .../PacktLibrary/DisplacementVector.cs | 22 +++ vscode/Chapter06/PacktLibrary/DvdPlayer.cs | 14 ++ vscode/Chapter06/PacktLibrary/Employee.cs | 22 +++ vscode/Chapter06/PacktLibrary/IPlayable.cs | 11 ++ .../PacktLibrary/PacktLibrary.csproj | 13 ++ vscode/Chapter06/PacktLibrary/Person.cs | 98 ++++++++++ .../Chapter06/PacktLibrary/PersonComparer.cs | 56 ++++++ .../Chapter06/PacktLibrary/PersonException.cs | 11 ++ .../PacktLibrary/StringExtensions.cs | 15 ++ vscode/Chapter06/PeopleApp/PeopleApp.csproj | 19 ++ .../PeopleApp/Program.EventHandlers.cs | 24 +++ vscode/Chapter06/PeopleApp/Program.Helpers.cs | 19 ++ vscode/Chapter06/PeopleApp/Program.cs | 184 ++++++++++++++++++ 62 files changed, 1661 insertions(+), 2 deletions(-) create mode 100644 vs4win/Chapter05/Namespaces/France.Paris.cs create mode 100644 vs4win/Chapter05/Namespaces/Namespaces.csproj create mode 100644 vs4win/Chapter05/Namespaces/Program.cs create mode 100644 vs4win/Chapter05/Namespaces/Texas.Paris.cs create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Circle.cs create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Program.cs create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Rectangle.cs create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Shape.cs create mode 100644 vs4win/Chapter06/Ch06Ex02Inheritance/Square.cs create mode 100644 vs4win/Chapter06/Chapter06.sln create mode 100644 vs4win/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj create mode 100644 vs4win/Chapter06/CodeAnalyzing/Program.cs create mode 100644 vs4win/Chapter06/CodeAnalyzing/stylecop.json create mode 100644 vs4win/Chapter06/NullHandling/Address.cs create mode 100644 vs4win/Chapter06/NullHandling/NullHandling.csproj create mode 100644 vs4win/Chapter06/NullHandling/Program.cs create mode 100644 vs4win/Chapter06/PacktLibrary/DisplacementVector.cs create mode 100644 vs4win/Chapter06/PacktLibrary/DvdPlayer.cs create mode 100644 vs4win/Chapter06/PacktLibrary/Employee.cs create mode 100644 vs4win/Chapter06/PacktLibrary/IPlayable.cs create mode 100644 vs4win/Chapter06/PacktLibrary/PacktLibrary.csproj create mode 100644 vs4win/Chapter06/PacktLibrary/Person.cs create mode 100644 vs4win/Chapter06/PacktLibrary/PersonComparer.cs create mode 100644 vs4win/Chapter06/PacktLibrary/PersonException.cs create mode 100644 vs4win/Chapter06/PacktLibrary/StringExtensions.cs create mode 100644 vs4win/Chapter06/PeopleApp/PeopleApp.csproj create mode 100644 vs4win/Chapter06/PeopleApp/Program.EventHandlers.cs create mode 100644 vs4win/Chapter06/PeopleApp/Program.Helpers.cs create mode 100644 vs4win/Chapter06/PeopleApp/Program.cs create mode 100644 vscode/Chapter05/Namespaces/France.Paris.cs create mode 100644 vscode/Chapter05/Namespaces/Namespaces.csproj create mode 100644 vscode/Chapter05/Namespaces/Program.cs create mode 100644 vscode/Chapter05/Namespaces/Texas.Paris.cs create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Ch06Ex02Inheritance.csproj create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Circle.cs create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Program.cs create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Rectangle.cs create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Shape.cs create mode 100644 vscode/Chapter06/Ch06Ex02Inheritance/Square.cs create mode 100644 vscode/Chapter06/Chapter06.code-workspace create mode 100644 vscode/Chapter06/CodeAnalyzing/CodeAnalyzing.csproj create mode 100644 vscode/Chapter06/CodeAnalyzing/Program.cs create mode 100644 vscode/Chapter06/CodeAnalyzing/stylecop.json create mode 100644 vscode/Chapter06/NullHandling/Address.cs create mode 100644 vscode/Chapter06/NullHandling/NullHandling.csproj create mode 100644 vscode/Chapter06/NullHandling/Program.cs create mode 100644 vscode/Chapter06/PacktLibrary/DisplacementVector.cs create mode 100644 vscode/Chapter06/PacktLibrary/DvdPlayer.cs create mode 100644 vscode/Chapter06/PacktLibrary/Employee.cs create mode 100644 vscode/Chapter06/PacktLibrary/IPlayable.cs create mode 100644 vscode/Chapter06/PacktLibrary/PacktLibrary.csproj create mode 100644 vscode/Chapter06/PacktLibrary/Person.cs create mode 100644 vscode/Chapter06/PacktLibrary/PersonComparer.cs create mode 100644 vscode/Chapter06/PacktLibrary/PersonException.cs create mode 100644 vscode/Chapter06/PacktLibrary/StringExtensions.cs create mode 100644 vscode/Chapter06/PeopleApp/PeopleApp.csproj create mode 100644 vscode/Chapter06/PeopleApp/Program.EventHandlers.cs create mode 100644 vscode/Chapter06/PeopleApp/Program.Helpers.cs create mode 100644 vscode/Chapter06/PeopleApp/Program.cs 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());