Initial commit

This commit is contained in:
Mark J Price 2022-02-19 19:56:52 +00:00
parent e523533d17
commit 10cceacca6
50 changed files with 1280 additions and 0 deletions

View file

@ -0,0 +1,10 @@
namespace CalculatorLib
{
public class Calculator
{
public double Add(double a, double b)
{
return a + b;
}
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CalculatorLib\CalculatorLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,35 @@
using CalculatorLib;
namespace CalculatorLibUnitTests
{
public class CalculatorUnitTests
{
[Fact]
public void TestAdding2And2()
{
// arrange
double a = 2;
double b = 2;
double expected = 4;
Calculator calc = new();
// act
double actual = calc.Add(a, b);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void TestAdding2And3()
{
// arrange
double a = 2;
double b = 3;
double expected = 5;
Calculator calc = new();
// act
double actual = calc.Add(a, b);
// assert
Assert.Equal(expected, actual);
}
}
}

View file

@ -0,0 +1 @@
global using Xunit;

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>
<ProjectReference Include="..\CallStackExceptionHandlingLib\CallStackExceptionHandlingLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,25 @@
using CallStackExceptionHandlingLib;
using static System.Console;
WriteLine("In Main");
Alpha();
void Alpha()
{
WriteLine("In Alpha");
Beta();
}
void Beta()
{
WriteLine("In Beta");
try
{
Calculator.Gamma();
}
catch (Exception ex)
{
WriteLine($"Caught this: {ex.Message}");
throw ex;
}
}

View file

@ -0,0 +1,19 @@
using static System.Console;
namespace CallStackExceptionHandlingLib
{
public class Calculator
{
public static void Gamma() // public so it can be called from outside
{
WriteLine("In Gamma");
Delta();
}
private static void Delta() // private so it can only be called internally
{
WriteLine("In Delta");
File.OpenText("bad file path");
}
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

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>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ch04Ex02PrimeFactorsLib\Ch04Ex02PrimeFactorsLib.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,10 @@
using Ch04Ex02PrimeFactorsLib;
Write("Enter a number between 1 and 1000: ");
if (int.TryParse(ReadLine(), out int number))
{
WriteLine(format: "Prime factors of {0} are: {1}",
arg0: number,
arg1: Primes.PrimeFactors(number));
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,39 @@
namespace Ch04Ex02PrimeFactorsLib
{
public class Primes
{
public static int[] PrimeNumbers = new[]
{
97, 89, 83, 79, 73, 71, 67, 61, 59, 53,
47, 43, 41, 37, 31, 29, 23, 19, 17, 13,
11, 7, 5, 3, 2
};
public static string PrimeFactors(int number)
{
string factors = string.Empty;
foreach (int divisor in PrimeNumbers)
{
int remainder;
do
{
remainder = number % divisor;
if (remainder == 0)
{
number = number / divisor;
if (number == 1)
{
factors += $"{divisor}";
}
else
{
factors += $"{divisor} x ";
}
}
} while (remainder == 0);
}
return $"{factors}";
}
}
}

View file

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ch04Ex02PrimeFactorsLib\Ch04Ex02PrimeFactorsLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,35 @@
using Ch04Ex02PrimeFactorsLib;
namespace Ch04Ex02PrimeFactorsTests
{
public class PrimeFactorsUnitTests
{
[Fact]
public void PrimeFactorsOf40()
{
// arrange
int number = 40;
string expected = "5 x 2 x 2 x 2";
// act
string actual = Primes.PrimeFactors(number);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void PrimeFactorsOf99()
{
// arrange
int number = 99;
string expected = "11 x 3 x 3";
// act
string actual = Primes.PrimeFactors(number);
// assert
Assert.Equal(expected, actual);
}
}
}

View file

@ -0,0 +1 @@
global using Xunit;

View file

@ -0,0 +1,79 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32210.238
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WritingFunctions", "WritingFunctions\WritingFunctions.csproj", "{59DFA8EE-F2D8-40A0-8E17-EB249443B109}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Debugging", "Debugging\Debugging.csproj", "{4FC54815-4A47-4B64-B3BF-BABE64AA7D2D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Instrumenting", "Instrumenting\Instrumenting.csproj", "{8061BFA7-C0A6-48BD-BE64-64501621429C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CalculatorLib", "CalculatorLib\CalculatorLib.csproj", "{07863BDC-DBD6-4714-9A98-59A6930ECB6F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CalculatorLibUnitTests", "CalculatorLibUnitTests\CalculatorLibUnitTests.csproj", "{6F3D5375-6D85-4A79-97A2-3605347BE4BE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CallStackExceptionHandlingLib", "CallStackExceptionHandlingLib\CallStackExceptionHandlingLib.csproj", "{B6B0B88B-66E7-4599-ABA8-E9DC9BF2EF57}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CallStackExceptionHandling", "CallStackExceptionHandling\CallStackExceptionHandling.csproj", "{B856E873-E17A-400D-98B5-165C3DF976AF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch04Ex02PrimeFactorsApp", "Ch04Ex02PrimeFactorsApp\Ch04Ex02PrimeFactorsApp.csproj", "{3B2B2F8A-FCB9-4C9D-85EE-D2433213D771}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch04Ex02PrimeFactorsLib", "Ch04Ex02PrimeFactorsLib\Ch04Ex02PrimeFactorsLib.csproj", "{5BD87DA8-3F4B-4CF7-A225-3E7030A1944C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch04Ex02PrimeFactorsTests", "Ch04Ex02PrimeFactorsTests\Ch04Ex02PrimeFactorsTests.csproj", "{878F1F7E-D3AD-4BF2-A66E-4EDDE7229566}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{59DFA8EE-F2D8-40A0-8E17-EB249443B109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59DFA8EE-F2D8-40A0-8E17-EB249443B109}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59DFA8EE-F2D8-40A0-8E17-EB249443B109}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59DFA8EE-F2D8-40A0-8E17-EB249443B109}.Release|Any CPU.Build.0 = Release|Any CPU
{4FC54815-4A47-4B64-B3BF-BABE64AA7D2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FC54815-4A47-4B64-B3BF-BABE64AA7D2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FC54815-4A47-4B64-B3BF-BABE64AA7D2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FC54815-4A47-4B64-B3BF-BABE64AA7D2D}.Release|Any CPU.Build.0 = Release|Any CPU
{8061BFA7-C0A6-48BD-BE64-64501621429C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8061BFA7-C0A6-48BD-BE64-64501621429C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8061BFA7-C0A6-48BD-BE64-64501621429C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8061BFA7-C0A6-48BD-BE64-64501621429C}.Release|Any CPU.Build.0 = Release|Any CPU
{07863BDC-DBD6-4714-9A98-59A6930ECB6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07863BDC-DBD6-4714-9A98-59A6930ECB6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07863BDC-DBD6-4714-9A98-59A6930ECB6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07863BDC-DBD6-4714-9A98-59A6930ECB6F}.Release|Any CPU.Build.0 = Release|Any CPU
{6F3D5375-6D85-4A79-97A2-3605347BE4BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F3D5375-6D85-4A79-97A2-3605347BE4BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F3D5375-6D85-4A79-97A2-3605347BE4BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F3D5375-6D85-4A79-97A2-3605347BE4BE}.Release|Any CPU.Build.0 = Release|Any CPU
{B6B0B88B-66E7-4599-ABA8-E9DC9BF2EF57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6B0B88B-66E7-4599-ABA8-E9DC9BF2EF57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6B0B88B-66E7-4599-ABA8-E9DC9BF2EF57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6B0B88B-66E7-4599-ABA8-E9DC9BF2EF57}.Release|Any CPU.Build.0 = Release|Any CPU
{B856E873-E17A-400D-98B5-165C3DF976AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B856E873-E17A-400D-98B5-165C3DF976AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B856E873-E17A-400D-98B5-165C3DF976AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B856E873-E17A-400D-98B5-165C3DF976AF}.Release|Any CPU.Build.0 = Release|Any CPU
{3B2B2F8A-FCB9-4C9D-85EE-D2433213D771}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B2B2F8A-FCB9-4C9D-85EE-D2433213D771}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B2B2F8A-FCB9-4C9D-85EE-D2433213D771}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B2B2F8A-FCB9-4C9D-85EE-D2433213D771}.Release|Any CPU.Build.0 = Release|Any CPU
{5BD87DA8-3F4B-4CF7-A225-3E7030A1944C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BD87DA8-3F4B-4CF7-A225-3E7030A1944C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BD87DA8-3F4B-4CF7-A225-3E7030A1944C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BD87DA8-3F4B-4CF7-A225-3E7030A1944C}.Release|Any CPU.Build.0 = Release|Any CPU
{878F1F7E-D3AD-4BF2-A66E-4EDDE7229566}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{878F1F7E-D3AD-4BF2-A66E-4EDDE7229566}.Debug|Any CPU.Build.0 = Debug|Any CPU
{878F1F7E-D3AD-4BF2-A66E-4EDDE7229566}.Release|Any CPU.ActiveCfg = Release|Any CPU
{878F1F7E-D3AD-4BF2-A66E-4EDDE7229566}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DF0D726D-6818-48B7-9F87-CBE3EA568974}
EndGlobalSection
EndGlobal

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,12 @@
double a = 4.5;
double b = 2.5;
double answer = Add(a, b);
WriteLine($"{a} + {b} = {answer}");
WriteLine("Press ENTER to end the app.");
ReadLine(); // wait for user to press ENTER
double Add(double a, double b)
{
return a + b; // deliberate bug!
}

View file

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0-preview.1.22076.8" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,43 @@
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
string logPath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.DesktopDirectory), "log.txt");
Console.WriteLine($"Writing to: {logPath}");
TextWriterTraceListener logFile = new(File.CreateText(logPath));
Trace.Listeners.Add(logFile);
// text writer is buffered, so this option calls
// Flush() on all listeners after writing
Trace.AutoFlush = true;
Debug.WriteLine("Debug says, I am watching!");
Trace.WriteLine("Trace says, I am watching!");
Console.WriteLine("Reading from appsettings.json in {0}",
arg0: Directory.GetCurrentDirectory());
ConfigurationBuilder builder = new();
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonFile("appsettings.json",
optional: false, reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
TraceSwitch ts = new(
displayName: "PacktSwitch",
description: "This switch is set via a JSON config.");
configuration.GetSection("PacktSwitch").Bind(ts);
Trace.WriteLineIf(ts.TraceError, "Trace error");
Trace.WriteLineIf(ts.TraceWarning, "Trace warning");
Trace.WriteLineIf(ts.TraceInfo, "Trace information");
Trace.WriteLineIf(ts.TraceVerbose, "Trace verbose");
Console.ReadLine();

View file

@ -0,0 +1,5 @@
{
"PacktSwitch": {
"Level": "Info"
}
}

View file

@ -0,0 +1,170 @@
partial class Program
{
static void TimesTable(byte number, byte size = 12)
{
WriteLine($"This is the {number} times table with {size} rows:");
for (int row = 1; row <= size; row++)
{
WriteLine($"{row} x {number} = {row * number}");
}
WriteLine();
}
static decimal CalculateTax(
decimal amount, string twoLetterRegionCode)
{
decimal rate = 0.0M;
switch (twoLetterRegionCode)
{
case "CH": // Switzerland
rate = 0.08M;
break;
case "DK": // Denmark
case "NO": // Norway
rate = 0.25M;
break;
case "GB": // United Kingdom
case "FR": // France
rate = 0.2M;
break;
case "HU": // Hungary
rate = 0.27M;
break;
case "OR": // Oregon
case "AK": // Alaska
case "MT": // Montana
rate = 0.0M;
break;
case "ND": // North Dakota
case "WI": // Wisconsin
case "ME": // Maine
case "VA": // Virginia
rate = 0.05M;
break;
case "CA": // California
rate = 0.0825M;
break;
default: // most US states
rate = 0.06M;
break;
}
return amount * rate;
}
/// <summary>
/// Pass a 32-bit integer and it will be converted into its ordinal equivalent.
/// </summary>
/// <param name="number">Number is a cardinal value e.g. 1, 2, 3, and so on.</param>
/// <returns>Number as an ordinal value e.g. 1st, 2nd, 3rd, and so on.</returns>
static string CardinalToOrdinal(int number)
{
switch (number)
{
case 11: // special cases for 11th to 13th
case 12:
case 13:
return $"{number}th";
default:
int lastDigit = number % 10;
string suffix = lastDigit switch
{
1 => "st",
2 => "nd",
3 => "rd",
_ => "th"
};
return $"{number}{suffix}";
}
}
static void RunCardinalToOrdinal()
{
for (int number = 1; number <= 40; number++)
{
Write($"{CardinalToOrdinal(number)} ");
}
WriteLine();
}
static int Factorial(int number)
{
if (number < 0)
{
throw new ArgumentException(message:
"The factorial function is defined for non-negative integers only.",
paramName: "number");
}
else if (number == 0)
{
return 1;
}
else
{
checked // for overflow
{
return number * Factorial(number - 1);
}
}
}
static void RunFactorial()
{
for (int i = 1; i <= 14; i++)
{
try
{
WriteLine($"{i}! = {Factorial(i):N0}");
}
catch (System.OverflowException)
{
WriteLine($"{i}! is too big for a 32-bit integer.");
}
}
}
static int FibImperative(int term)
{
if (term == 1)
{
return 0;
}
else if (term == 2)
{
return 1;
}
else
{
return FibImperative(term - 1) + FibImperative(term - 2);
}
}
static void RunFibImperative()
{
for (int i = 1; i <= 30; i++)
{
WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
arg0: CardinalToOrdinal(i),
arg1: FibImperative(term: i));
}
}
static int FibFunctional(int term) =>
term switch
{
1 => 0,
2 => 1,
_ => FibFunctional(term - 1) + FibFunctional(term - 2)
};
static void RunFibFunctional()
{
for (int i = 1; i <= 30; i++)
{
WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
arg0: CardinalToOrdinal(i),
arg1: FibFunctional(term: i));
}
}
}

View file

@ -0,0 +1,20 @@
/*
TimesTable(7);
TimesTable(7, 20);
TimesTable(number: 7, size: 10);
*/
/*
decimal taxToPay = CalculateTax(amount: 149, twoLetterRegionCode: "FR");
WriteLine($"You must pay {taxToPay} in tax.");
*/
//RunCardinalToOrdinal();
//RunFactorial();
//RunFibImperative();
RunFibFunctional();

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 @@
namespace CalculatorLib
{
public class Calculator
{
public double Add(double a, double b)
{
return a + b;
}
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CalculatorLib\CalculatorLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,35 @@
using CalculatorLib;
namespace CalculatorLibUnitTests
{
public class CalculatorUnitTests
{
[Fact]
public void TestAdding2And2()
{
// arrange
double a = 2;
double b = 2;
double expected = 4;
Calculator calc = new();
// act
double actual = calc.Add(a, b);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void TestAdding2And3()
{
// arrange
double a = 2;
double b = 3;
double expected = 5;
Calculator calc = new();
// act
double actual = calc.Add(a, b);
// assert
Assert.Equal(expected, actual);
}
}
}

View file

@ -0,0 +1 @@
global using Xunit;

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>
<ProjectReference Include="..\CallStackExceptionHandlingLib\CallStackExceptionHandlingLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,25 @@
using CallStackExceptionHandlingLib;
using static System.Console;
WriteLine("In Main");
Alpha();
void Alpha()
{
WriteLine("In Alpha");
Beta();
}
void Beta()
{
WriteLine("In Beta");
try
{
Calculator.Gamma();
}
catch (Exception ex)
{
WriteLine($"Caught this: {ex.Message}");
throw ex;
}
}

View file

@ -0,0 +1,19 @@
using static System.Console;
namespace CallStackExceptionHandlingLib
{
public class Calculator
{
public static void Gamma() // public so it can be called from outside
{
WriteLine("In Gamma");
Delta();
}
private static void Delta() // private so it can only be called internally
{
WriteLine("In Delta");
File.OpenText("bad file path");
}
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

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>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ch04Ex02PrimeFactorsLib\Ch04Ex02PrimeFactorsLib.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Console" Static="true" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,10 @@
using Ch04Ex02PrimeFactorsLib;
Write("Enter a number between 1 and 1000: ");
if (int.TryParse(ReadLine(), out int number))
{
WriteLine(format: "Prime factors of {0} are: {1}",
arg0: number,
arg1: Primes.PrimeFactors(number));
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,39 @@
namespace Ch04Ex02PrimeFactorsLib
{
public class Primes
{
public static int[] PrimeNumbers = new[]
{
97, 89, 83, 79, 73, 71, 67, 61, 59, 53,
47, 43, 41, 37, 31, 29, 23, 19, 17, 13,
11, 7, 5, 3, 2
};
public static string PrimeFactors(int number)
{
string factors = string.Empty;
foreach (int divisor in PrimeNumbers)
{
int remainder;
do
{
remainder = number % divisor;
if (remainder == 0)
{
number = number / divisor;
if (number == 1)
{
factors += $"{divisor}";
}
else
{
factors += $"{divisor} x ";
}
}
} while (remainder == 0);
}
return $"{factors}";
}
}
}

View file

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ch04Ex02PrimeFactorsLib\Ch04Ex02PrimeFactorsLib.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,35 @@
using Ch04Ex02PrimeFactorsLib;
namespace Ch04Ex02PrimeFactorsTests
{
public class PrimeFactorsUnitTests
{
[Fact]
public void PrimeFactorsOf40()
{
// arrange
int number = 40;
string expected = "5 x 2 x 2 x 2";
// act
string actual = Primes.PrimeFactors(number);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void PrimeFactorsOf99()
{
// arrange
int number = 99;
string expected = "11 x 3 x 3";
// act
string actual = Primes.PrimeFactors(number);
// assert
Assert.Equal(expected, actual);
}
}
}

View file

@ -0,0 +1 @@
global using Xunit;

View file

@ -0,0 +1,19 @@
{
"folders": [
{
"path": "WritingFunctions"
},
{
"path": "Debugging"
},
{
"path": "Instrumenting"
},
{
"path": "CalculatorLib"
},
{
"path": "CalculatorLibUnitTests"
}
]
}

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,12 @@
double a = 4.5;
double b = 2.5;
double answer = Add(a, b);
WriteLine($"{a} + {b} = {answer}");
WriteLine("Press ENTER to end the app.");
ReadLine(); // wait for user to press ENTER
double Add(double a, double b)
{
return a + b; // deliberate bug!
}

View file

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0-preview.1.22076.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0-preview.1.22076.8" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,43 @@
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
string logPath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.DesktopDirectory), "log.txt");
Console.WriteLine($"Writing to: {logPath}");
TextWriterTraceListener logFile = new(File.CreateText(logPath));
Trace.Listeners.Add(logFile);
// text writer is buffered, so this option calls
// Flush() on all listeners after writing
Trace.AutoFlush = true;
Debug.WriteLine("Debug says, I am watching!");
Trace.WriteLine("Trace says, I am watching!");
Console.WriteLine("Reading from appsettings.json in {0}",
arg0: Directory.GetCurrentDirectory());
ConfigurationBuilder builder = new();
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonFile("appsettings.json",
optional: false, reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
TraceSwitch ts = new(
displayName: "PacktSwitch",
description: "This switch is set via a JSON config.");
configuration.GetSection("PacktSwitch").Bind(ts);
Trace.WriteLineIf(ts.TraceError, "Trace error");
Trace.WriteLineIf(ts.TraceWarning, "Trace warning");
Trace.WriteLineIf(ts.TraceInfo, "Trace information");
Trace.WriteLineIf(ts.TraceVerbose, "Trace verbose");
Console.ReadLine();

View file

@ -0,0 +1,5 @@
{
"PacktSwitch": {
"Level": "Info"
}
}

View file

@ -0,0 +1,170 @@
partial class Program
{
static void TimesTable(byte number, byte size = 12)
{
WriteLine($"This is the {number} times table with {size} rows:");
for (int row = 1; row <= size; row++)
{
WriteLine($"{row} x {number} = {row * number}");
}
WriteLine();
}
static decimal CalculateTax(
decimal amount, string twoLetterRegionCode)
{
decimal rate = 0.0M;
switch (twoLetterRegionCode)
{
case "CH": // Switzerland
rate = 0.08M;
break;
case "DK": // Denmark
case "NO": // Norway
rate = 0.25M;
break;
case "GB": // United Kingdom
case "FR": // France
rate = 0.2M;
break;
case "HU": // Hungary
rate = 0.27M;
break;
case "OR": // Oregon
case "AK": // Alaska
case "MT": // Montana
rate = 0.0M;
break;
case "ND": // North Dakota
case "WI": // Wisconsin
case "ME": // Maine
case "VA": // Virginia
rate = 0.05M;
break;
case "CA": // California
rate = 0.0825M;
break;
default: // most US states
rate = 0.06M;
break;
}
return amount * rate;
}
/// <summary>
/// Pass a 32-bit integer and it will be converted into its ordinal equivalent.
/// </summary>
/// <param name="number">Number is a cardinal value e.g. 1, 2, 3, and so on.</param>
/// <returns>Number as an ordinal value e.g. 1st, 2nd, 3rd, and so on.</returns>
static string CardinalToOrdinal(int number)
{
switch (number)
{
case 11: // special cases for 11th to 13th
case 12:
case 13:
return $"{number}th";
default:
int lastDigit = number % 10;
string suffix = lastDigit switch
{
1 => "st",
2 => "nd",
3 => "rd",
_ => "th"
};
return $"{number}{suffix}";
}
}
static void RunCardinalToOrdinal()
{
for (int number = 1; number <= 40; number++)
{
Write($"{CardinalToOrdinal(number)} ");
}
WriteLine();
}
static int Factorial(int number)
{
if (number < 0)
{
throw new ArgumentException(message:
"The factorial function is defined for non-negative integers only.",
paramName: "number");
}
else if (number == 0)
{
return 1;
}
else
{
checked // for overflow
{
return number * Factorial(number - 1);
}
}
}
static void RunFactorial()
{
for (int i = 1; i <= 14; i++)
{
try
{
WriteLine($"{i}! = {Factorial(i):N0}");
}
catch (System.OverflowException)
{
WriteLine($"{i}! is too big for a 32-bit integer.");
}
}
}
static int FibImperative(int term)
{
if (term == 1)
{
return 0;
}
else if (term == 2)
{
return 1;
}
else
{
return FibImperative(term - 1) + FibImperative(term - 2);
}
}
static void RunFibImperative()
{
for (int i = 1; i <= 30; i++)
{
WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
arg0: CardinalToOrdinal(i),
arg1: FibImperative(term: i));
}
}
static int FibFunctional(int term) =>
term switch
{
1 => 0,
2 => 1,
_ => FibFunctional(term - 1) + FibFunctional(term - 2)
};
static void RunFibFunctional()
{
for (int i = 1; i <= 30; i++)
{
WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
arg0: CardinalToOrdinal(i),
arg1: FibFunctional(term: i));
}
}
}

View file

@ -0,0 +1,20 @@
/*
TimesTable(7);
TimesTable(7, 20);
TimesTable(number: 7, size: 10);
*/
/*
decimal taxToPay = CalculateTax(amount: 149, twoLetterRegionCode: "FR");
WriteLine($"You must pay {taxToPay} in tax.");
*/
//RunCardinalToOrdinal();
//RunFactorial();
//RunFibImperative();
RunFibFunctional();

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>