diff --git a/vs4win/Chapter04/CalculatorLib/Calculator.cs b/vs4win/Chapter04/CalculatorLib/Calculator.cs new file mode 100644 index 0000000..9dc6c89 --- /dev/null +++ b/vs4win/Chapter04/CalculatorLib/Calculator.cs @@ -0,0 +1,10 @@ +namespace CalculatorLib +{ + public class Calculator + { + public double Add(double a, double b) + { + return a + b; + } + } +} \ No newline at end of file diff --git a/vs4win/Chapter04/CalculatorLib/CalculatorLib.csproj b/vs4win/Chapter04/CalculatorLib/CalculatorLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vs4win/Chapter04/CalculatorLib/CalculatorLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj b/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj new file mode 100644 index 0000000..7f1fa4b --- /dev/null +++ b/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj @@ -0,0 +1,27 @@ + + + + net7.0 + enable + enable + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs b/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs new file mode 100644 index 0000000..5e6128e --- /dev/null +++ b/vs4win/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/vs4win/Chapter04/CalculatorLibUnitTests/Usings.cs b/vs4win/Chapter04/CalculatorLibUnitTests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/vs4win/Chapter04/CalculatorLibUnitTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/vs4win/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj b/vs4win/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj new file mode 100644 index 0000000..197b64c --- /dev/null +++ b/vs4win/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/vs4win/Chapter04/CallStackExceptionHandling/Program.cs b/vs4win/Chapter04/CallStackExceptionHandling/Program.cs new file mode 100644 index 0000000..12746c0 --- /dev/null +++ b/vs4win/Chapter04/CallStackExceptionHandling/Program.cs @@ -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; + } +} diff --git a/vs4win/Chapter04/CallStackExceptionHandlingLib/Calculator.cs b/vs4win/Chapter04/CallStackExceptionHandlingLib/Calculator.cs new file mode 100644 index 0000000..748d4dd --- /dev/null +++ b/vs4win/Chapter04/CallStackExceptionHandlingLib/Calculator.cs @@ -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"); + } + } +} diff --git a/vs4win/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj b/vs4win/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vs4win/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj b/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj new file mode 100644 index 0000000..95b2a42 --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj @@ -0,0 +1,19 @@ + + + + Exe + net7.0 + enable + enable + preview + + + + + + + + + + + diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs b/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs new file mode 100644 index 0000000..b0a492a --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs @@ -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)); +} diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj b/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs b/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs new file mode 100644 index 0000000..f8f4281 --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs @@ -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}"; + } + } +} \ No newline at end of file diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj new file mode 100644 index 0000000..2ac4e3d --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs new file mode 100644 index 0000000..4f88eba --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs @@ -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); + } + } +} diff --git a/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/vs4win/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/vs4win/Chapter04/Chapter04.sln b/vs4win/Chapter04/Chapter04.sln new file mode 100644 index 0000000..da1dca3 --- /dev/null +++ b/vs4win/Chapter04/Chapter04.sln @@ -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 diff --git a/vs4win/Chapter04/Debugging/Debugging.csproj b/vs4win/Chapter04/Debugging/Debugging.csproj new file mode 100644 index 0000000..61f4e03 --- /dev/null +++ b/vs4win/Chapter04/Debugging/Debugging.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/vs4win/Chapter04/Debugging/Program.cs b/vs4win/Chapter04/Debugging/Program.cs new file mode 100644 index 0000000..910c058 --- /dev/null +++ b/vs4win/Chapter04/Debugging/Program.cs @@ -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! +} diff --git a/vs4win/Chapter04/Instrumenting/Instrumenting.csproj b/vs4win/Chapter04/Instrumenting/Instrumenting.csproj new file mode 100644 index 0000000..b879c25 --- /dev/null +++ b/vs4win/Chapter04/Instrumenting/Instrumenting.csproj @@ -0,0 +1,23 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + + + PreserveNewest + + + + diff --git a/vs4win/Chapter04/Instrumenting/Program.cs b/vs4win/Chapter04/Instrumenting/Program.cs new file mode 100644 index 0000000..3460f77 --- /dev/null +++ b/vs4win/Chapter04/Instrumenting/Program.cs @@ -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(); \ No newline at end of file diff --git a/vs4win/Chapter04/Instrumenting/appsettings.json b/vs4win/Chapter04/Instrumenting/appsettings.json new file mode 100644 index 0000000..37790aa --- /dev/null +++ b/vs4win/Chapter04/Instrumenting/appsettings.json @@ -0,0 +1,5 @@ +{ + "PacktSwitch": { + "Level": "Info" + } +} diff --git a/vs4win/Chapter04/WritingFunctions/Program.Functions.cs b/vs4win/Chapter04/WritingFunctions/Program.Functions.cs new file mode 100644 index 0000000..8297031 --- /dev/null +++ b/vs4win/Chapter04/WritingFunctions/Program.Functions.cs @@ -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; + } + + /// + /// Pass a 32-bit integer and it will be converted into its ordinal equivalent. + /// + /// Number is a cardinal value e.g. 1, 2, 3, and so on. + /// Number as an ordinal value e.g. 1st, 2nd, 3rd, and so on. + + 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)); + } + } + +} diff --git a/vs4win/Chapter04/WritingFunctions/Program.cs b/vs4win/Chapter04/WritingFunctions/Program.cs new file mode 100644 index 0000000..f2a87e5 --- /dev/null +++ b/vs4win/Chapter04/WritingFunctions/Program.cs @@ -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(); \ No newline at end of file diff --git a/vs4win/Chapter04/WritingFunctions/WritingFunctions.csproj b/vs4win/Chapter04/WritingFunctions/WritingFunctions.csproj new file mode 100644 index 0000000..05635b2 --- /dev/null +++ b/vs4win/Chapter04/WritingFunctions/WritingFunctions.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/vscode/Chapter04/CalculatorLib/Calculator.cs b/vscode/Chapter04/CalculatorLib/Calculator.cs new file mode 100644 index 0000000..9dc6c89 --- /dev/null +++ b/vscode/Chapter04/CalculatorLib/Calculator.cs @@ -0,0 +1,10 @@ +namespace CalculatorLib +{ + public class Calculator + { + public double Add(double a, double b) + { + return a + b; + } + } +} \ No newline at end of file diff --git a/vscode/Chapter04/CalculatorLib/CalculatorLib.csproj b/vscode/Chapter04/CalculatorLib/CalculatorLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vscode/Chapter04/CalculatorLib/CalculatorLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vscode/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj b/vscode/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj new file mode 100644 index 0000000..7f1fa4b --- /dev/null +++ b/vscode/Chapter04/CalculatorLibUnitTests/CalculatorLibUnitTests.csproj @@ -0,0 +1,27 @@ + + + + net7.0 + enable + enable + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/vscode/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs b/vscode/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs new file mode 100644 index 0000000..5e6128e --- /dev/null +++ b/vscode/Chapter04/CalculatorLibUnitTests/CalculatorUnitTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/vscode/Chapter04/CalculatorLibUnitTests/Usings.cs b/vscode/Chapter04/CalculatorLibUnitTests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/vscode/Chapter04/CalculatorLibUnitTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/vscode/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj b/vscode/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj new file mode 100644 index 0000000..197b64c --- /dev/null +++ b/vscode/Chapter04/CallStackExceptionHandling/CallStackExceptionHandling.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/vscode/Chapter04/CallStackExceptionHandling/Program.cs b/vscode/Chapter04/CallStackExceptionHandling/Program.cs new file mode 100644 index 0000000..12746c0 --- /dev/null +++ b/vscode/Chapter04/CallStackExceptionHandling/Program.cs @@ -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; + } +} diff --git a/vscode/Chapter04/CallStackExceptionHandlingLib/Calculator.cs b/vscode/Chapter04/CallStackExceptionHandlingLib/Calculator.cs new file mode 100644 index 0000000..748d4dd --- /dev/null +++ b/vscode/Chapter04/CallStackExceptionHandlingLib/Calculator.cs @@ -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"); + } + } +} diff --git a/vscode/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj b/vscode/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vscode/Chapter04/CallStackExceptionHandlingLib/CallStackExceptionHandlingLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj b/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj new file mode 100644 index 0000000..95b2a42 --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Ch04Ex02PrimeFactorsApp.csproj @@ -0,0 +1,19 @@ + + + + Exe + net7.0 + enable + enable + preview + + + + + + + + + + + diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs b/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs new file mode 100644 index 0000000..b0a492a --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsApp/Program.cs @@ -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)); +} diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj b/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj new file mode 100644 index 0000000..cfadb03 --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Ch04Ex02PrimeFactorsLib.csproj @@ -0,0 +1,9 @@ + + + + net7.0 + enable + enable + + + diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs b/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs new file mode 100644 index 0000000..f8f4281 --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsLib/Primes.cs @@ -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}"; + } + } +} \ No newline at end of file diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj new file mode 100644 index 0000000..2ac4e3d --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Ch04Ex02PrimeFactorsTests.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs new file mode 100644 index 0000000..4f88eba --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/PrimeFactorsUnitTests.cs @@ -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); + } + } +} diff --git a/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/vscode/Chapter04/Ch04Ex02PrimeFactorsTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/vscode/Chapter04/Chapter04.code-workspace b/vscode/Chapter04/Chapter04.code-workspace new file mode 100644 index 0000000..e23c290 --- /dev/null +++ b/vscode/Chapter04/Chapter04.code-workspace @@ -0,0 +1,19 @@ +{ + "folders": [ + { + "path": "WritingFunctions" + }, + { + "path": "Debugging" + }, + { + "path": "Instrumenting" + }, + { + "path": "CalculatorLib" + }, + { + "path": "CalculatorLibUnitTests" + } + ] +} \ No newline at end of file diff --git a/vscode/Chapter04/Debugging/Debugging.csproj b/vscode/Chapter04/Debugging/Debugging.csproj new file mode 100644 index 0000000..61f4e03 --- /dev/null +++ b/vscode/Chapter04/Debugging/Debugging.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/vscode/Chapter04/Debugging/Program.cs b/vscode/Chapter04/Debugging/Program.cs new file mode 100644 index 0000000..910c058 --- /dev/null +++ b/vscode/Chapter04/Debugging/Program.cs @@ -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! +} diff --git a/vscode/Chapter04/Instrumenting/Instrumenting.csproj b/vscode/Chapter04/Instrumenting/Instrumenting.csproj new file mode 100644 index 0000000..b879c25 --- /dev/null +++ b/vscode/Chapter04/Instrumenting/Instrumenting.csproj @@ -0,0 +1,23 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + + + PreserveNewest + + + + diff --git a/vscode/Chapter04/Instrumenting/Program.cs b/vscode/Chapter04/Instrumenting/Program.cs new file mode 100644 index 0000000..3460f77 --- /dev/null +++ b/vscode/Chapter04/Instrumenting/Program.cs @@ -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(); \ No newline at end of file diff --git a/vscode/Chapter04/Instrumenting/appsettings.json b/vscode/Chapter04/Instrumenting/appsettings.json new file mode 100644 index 0000000..37790aa --- /dev/null +++ b/vscode/Chapter04/Instrumenting/appsettings.json @@ -0,0 +1,5 @@ +{ + "PacktSwitch": { + "Level": "Info" + } +} diff --git a/vscode/Chapter04/WritingFunctions/Program.Functions.cs b/vscode/Chapter04/WritingFunctions/Program.Functions.cs new file mode 100644 index 0000000..8297031 --- /dev/null +++ b/vscode/Chapter04/WritingFunctions/Program.Functions.cs @@ -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; + } + + /// + /// Pass a 32-bit integer and it will be converted into its ordinal equivalent. + /// + /// Number is a cardinal value e.g. 1, 2, 3, and so on. + /// Number as an ordinal value e.g. 1st, 2nd, 3rd, and so on. + + 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)); + } + } + +} diff --git a/vscode/Chapter04/WritingFunctions/Program.cs b/vscode/Chapter04/WritingFunctions/Program.cs new file mode 100644 index 0000000..f2a87e5 --- /dev/null +++ b/vscode/Chapter04/WritingFunctions/Program.cs @@ -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(); \ No newline at end of file diff --git a/vscode/Chapter04/WritingFunctions/WritingFunctions.csproj b/vscode/Chapter04/WritingFunctions/WritingFunctions.csproj new file mode 100644 index 0000000..05635b2 --- /dev/null +++ b/vscode/Chapter04/WritingFunctions/WritingFunctions.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + +