Initial commit

This commit is contained in:
Mark J Price 2022-02-27 19:08:52 +00:00
parent bc96ccb183
commit 18f89e91d4
62 changed files with 1661 additions and 2 deletions

View file

@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.2.32210.308 VisualStudioVersion = 17.2.32210.308
MinimumVisualStudioVersion = 10.0.40219.1 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 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.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.ActiveCfg = Release|Any CPU
{DF7885A2-C9F1-4959-9D13-C72E5E77CCDA}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -0,0 +1,6 @@
namespace France
{
public class Paris
{
}
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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);

View file

@ -0,0 +1,6 @@
namespace Texas
{
public class Paris
{
}
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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;
}
}
}

View file

@ -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}");

View file

@ -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;
}
}
}

View file

@ -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; }
}

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Remove="stylecop.json" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,23 @@
// <copyright file="Program.cs" company="Packt">
// Copyright (c) Packt. All rights reserved.
// </copyright>
namespace CodeAnalyzing;
using System.Diagnostics;
/// <summary>
/// The main class for this console app.
/// </summary>
public class Program
{
/// <summary>
/// The main entry point for this console app.
/// </summary>
/// <param name="args">
/// A string array of arguments passed to the console app.
/// </param>
public static void Main(string[] args)
{
Debug.WriteLine("Hello, Debugger!");
}
}

View file

@ -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."
}
}
}

View file

@ -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;
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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<int>
Nullable<int> 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);

View file

@ -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);
}
}

View file

@ -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.");
}
}

View file

@ -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}";
}
}

View file

@ -0,0 +1,11 @@
namespace Packt.Shared;
public interface IPlayable
{
void Play();
void Pause();
void Stop() // default interface implementation
{
WriteLine("Default implementation of Stop.");
}
}

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,98 @@
namespace Packt.Shared;
public class Person : object, IComparable<Person?>
{
// 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}!");
}
}
}

View file

@ -0,0 +1,56 @@
namespace Packt.Shared;
public class PersonComparer : IComparer<Person?>
{
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;
}
}

View file

@ -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) { }
}

View file

@ -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\.-_]+");
}
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
<ItemGroup>
<ProjectReference
Include="..\PacktLibrary\PacktLibrary.csproj" />
</ItemGroup>
</Project>

View file

@ -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!");
}
}

View file

@ -0,0 +1,19 @@
using Packt.Shared;
partial class Program
{
static void OutputPeopleNames(IEnumerable<Person?> people, string title)
{
WriteLine(title);
foreach (Person? p in people)
{
WriteLine(" {0}",
p is null ? "<null> Person" : p.Name ?? "<null> Name");
/* if p is null then output: <null> Person
else output: p.Name
unless p.Name is null in which case output: <null> Name */
}
}
}

View file

@ -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<int, string> 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());

View file

@ -5,6 +5,9 @@
}, },
{ {
"path": "PeopleApp" "path": "PeopleApp"
},
{
"path": "Namespaces"
} }
] ]
} }

View file

@ -0,0 +1,6 @@
namespace France
{
public class Paris
{
}
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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);

View file

@ -0,0 +1,6 @@
namespace Texas
{
public class Paris
{
}
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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;
}
}
}

View file

@ -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}");

View file

@ -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;
}
}
}

View file

@ -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; }
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,19 @@
{
"folders": [
{
"path": "PacktLibrary"
},
{
"path": "PeopleApp"
},
{
"path": "NullHandling"
},
{
"path": "CodeAnalyzing"
},
{
"path": "Ch06Ex02Inheritance"
}
]
}

View file

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Remove="stylecop.json" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,23 @@
// <copyright file="Program.cs" company="Packt">
// Copyright (c) Packt. All rights reserved.
// </copyright>
namespace CodeAnalyzing;
using System.Diagnostics;
/// <summary>
/// The main class for this console app.
/// </summary>
public class Program
{
/// <summary>
/// The main entry point for this console app.
/// </summary>
/// <param name="args">
/// A string array of arguments passed to the console app.
/// </param>
public static void Main(string[] args)
{
Debug.WriteLine("Hello, Debugger!");
}
}

View file

@ -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."
}
}
}

View file

@ -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;
}

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -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<int>
Nullable<int> 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);

View file

@ -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);
}
}

View file

@ -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.");
}
}

View file

@ -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}";
}
}

View file

@ -0,0 +1,11 @@
namespace Packt.Shared;
public interface IPlayable
{
void Play();
void Pause();
void Stop() // default interface implementation
{
WriteLine("Default implementation of Stop.");
}
}

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,98 @@
namespace Packt.Shared;
public class Person : object, IComparable<Person?>
{
// 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}!");
}
}
}

View file

@ -0,0 +1,56 @@
namespace Packt.Shared;
public class PersonComparer : IComparer<Person?>
{
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;
}
}

View file

@ -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) { }
}

View file

@ -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\.-_]+");
}
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
<ItemGroup>
<ProjectReference
Include="..\PacktLibrary\PacktLibrary.csproj" />
</ItemGroup>
</Project>

View file

@ -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!");
}
}

View file

@ -0,0 +1,19 @@
using Packt.Shared;
partial class Program
{
static void OutputPeopleNames(IEnumerable<Person?> people, string title)
{
WriteLine(title);
foreach (Person? p in people)
{
WriteLine(" {0}",
p is null ? "<null> Person" : p.Name ?? "<null> Name");
/* if p is null then output: <null> Person
else output: p.Name
unless p.Name is null in which case output: <null> Name */
}
}
}

View file

@ -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<int, string> 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());