├── .gitignore ├── LICENSE ├── README.md └── src ├── .gitignore ├── EngineLibBase ├── EngineLibBase.csproj └── IEngine.cs ├── chapter_01 ├── Program.cs └── chapter_01.csproj ├── chapter_02 ├── Program.cs └── chapter_02.csproj ├── chapter_03 ├── Program.cs └── chapter_03.csproj ├── chapter_04 ├── chapter_04.sln └── chapter_04 │ ├── AccessModifiers.cs │ ├── Employee.cs │ ├── MassConverters.cs │ ├── Namespaces.cs │ ├── Point.cs │ ├── Priority.cs │ ├── Program.cs │ ├── Project.cs │ └── chapter_04.csproj ├── chapter_05 ├── chapter_05.sln └── chapter_05 │ ├── Complex.cs │ ├── Employee.cs │ ├── Game.cs │ ├── Program.cs │ └── chapter_05.csproj ├── chapter_06 ├── chapter_06.sln └── chapter_06 │ ├── CompareObjects.cs │ ├── ConflictingGenerics.cs │ ├── GenericDemo.cs │ ├── IMultiVariant.cs │ ├── Pair.cs │ ├── Point.cs │ ├── Program.cs │ ├── RestrictedDictionary.cs │ ├── Shape.cs │ └── chapter_06.csproj ├── chapter_07 ├── Program.cs └── chapter_07.csproj ├── chapter_08 ├── chapter_08_01 │ ├── Program.cs │ ├── chapter_08_01.csproj │ ├── version1.cs │ ├── version2.cs │ ├── version3.cs │ └── version4.cs ├── chapter_08_02 │ ├── Program.cs │ └── chapter_08_02.csproj ├── chapter_08_03 │ ├── Program.cs │ └── chapter_08_03.csproj ├── chapter_08_04 │ ├── Program.cs │ └── chapter_08_04.csproj ├── chapter_08_05 │ ├── Program.cs │ └── chapter_08_05.csproj └── chapter_08_06 │ ├── Program.cs │ └── chapter_08_06.csproj ├── chapter_09 ├── chapter_09_01 │ ├── Program.cs │ └── chapter_09_01.csproj ├── chapter_09_02 │ ├── Program.cs │ └── chapter_09_02.csproj ├── chapter_09_03 │ ├── Program.cs │ └── chapter_09_03.csproj ├── chapter_09_04 │ ├── Program.cs │ └── chapter_09_04.csproj └── chapter_09_05 │ ├── Program.cs │ └── chapter_09_05.csproj ├── chapter_10 ├── chapter_10_01 │ ├── Program.cs │ └── chapter_10_01.csproj ├── chapter_10_02 │ ├── Program.cs │ └── chapter_10_02.csproj ├── chapter_10_03 │ ├── Program.cs │ └── chapter_10_03.csproj ├── chapter_10_04 │ ├── Program.cs │ └── chapter_10_04.csproj └── chapter_10_05 │ ├── Program.cs │ └── chapter_10_05.csproj ├── chapter_11 ├── EngineLib │ ├── Engine.cs │ └── EngineLib.csproj ├── chapter_11_01 │ ├── Program.cs │ └── chapter_11_01.csproj ├── chapter_11_02 │ ├── Program.cs │ └── chapter_11_02.csproj ├── chapter_11_03 │ ├── Program.cs │ └── chapter_11_03.csproj ├── chapter_11_04 │ ├── Program.cs │ └── chapter_11_04.csproj └── chapter_11_05 │ ├── Program.cs │ └── chapter_11_05.csproj ├── chapter_12 ├── chapter_12_01 │ ├── CreateThread1.cs │ ├── CreateThread2.cs │ ├── FileWatcher.cs │ ├── Primes.cs │ ├── Program.cs │ └── chapter_12_01.csproj ├── chapter_12_02 │ ├── KernelVsUserMode.cs │ ├── Program.cs │ ├── SyncPingPong.cs │ ├── SyncShared.cs │ ├── SyncWaitMultiple.cs │ └── chapter_12_02.csproj ├── chapter_12_03_01 │ ├── DeBelloGallico_LiberI.txt │ ├── FileOperations.cs │ ├── Program.cs │ └── chapter_12_03_01.csproj ├── chapter_12_03_02 │ ├── Program.cs │ └── chapter_12_03_02.csproj ├── chapter_12_03_03 │ ├── Program.cs │ └── chapter_12_03_03.csproj ├── chapter_12_03_05 │ ├── DeBelloGallico_LiberI.txt │ ├── Program.cs │ └── chapter_12_03_05.csproj ├── chapter_12_03_06 │ ├── Program.cs │ └── chapter_12_03_06.csproj ├── chapter_12_03_08 │ ├── Program.cs │ ├── TaskAndExceptions.cs │ └── chapter_12_03_08.csproj ├── chapter_12_03_09 │ ├── Cancelling0.cs │ ├── Program.cs │ └── chapter_12_03_09.csproj ├── chapter_12_03_10 │ ├── MonitorProgress.cs │ ├── Program.cs │ └── chapter_12_03_10.csproj ├── chapter_12_03_11 │ ├── Parallelizing.cs │ ├── Program.cs │ └── chapter_12_03_11.csproj ├── chapter_12_03_12 │ ├── DeletionNotifier.cs │ ├── DeletionNotifier2.cs │ ├── DeletionNotifier3.cs │ ├── Program.cs │ └── chapter_12_03_12.csproj ├── chapter_12_03_13 │ ├── Program.cs │ ├── SyncContext.cs │ └── chapter_12_03_13.csproj └── chapter_12_03_WPF │ ├── App.xaml │ ├── App.xaml.cs │ ├── AssemblyInfo.cs │ ├── DeBelloGallico_LiberI.txt │ ├── ImageConverter.cs │ ├── ImageInfo.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── UserInterface.cs │ └── chapter_12_03_WPF.csproj ├── chapter_13 ├── chapter_13_01 │ ├── Program.cs │ └── chapter_13_01.csproj ├── chapter_13_02 │ ├── Program.cs │ └── chapter_13_02.csproj ├── chapter_13_03 │ ├── Program.cs │ └── chapter_13_03.csproj ├── chapter_13_04 │ ├── Program.cs │ └── chapter_13_04.csproj └── chapter_13_05 │ ├── Program.cs │ └── chapter_13_05.csproj ├── chapter_14 ├── chapter_14_01 │ ├── ErrorsVsExceptions.cs │ └── chapter_14_01.csproj ├── chapter_14_02_01 │ ├── Catching.cs │ └── chapter_14_02_01.csproj ├── chapter_14_02_02 │ ├── DeBelloGallico_LiberI.txt │ ├── EmptyFile.txt │ ├── ExceptionObject.cs │ └── chapter_14_02_02.csproj ├── chapter_14_02_03 │ ├── ConditionalCatch.cs │ └── chapter_14_02_03.csproj ├── chapter_14_02_04 │ ├── Throwing.cs │ └── chapter_14_02_04.csproj ├── chapter_14_02_04_benchmark │ ├── Program.cs │ ├── ThrowingPerf.cs │ └── chapter_14_02_04_benchmark.csproj ├── chapter_14_02_05 │ ├── CustomExceptions.cs │ └── chapter_14_02_05.csproj ├── chapter_14_02_06 │ ├── Rethrowing1.cs │ ├── Rethrowing2.cs │ └── chapter_14_02_06.csproj ├── chapter_14_02_07 │ ├── Finally.cs │ └── chapter_14_02_07.csproj └── chapter_14_03 │ ├── ExceptionEvent.cs │ ├── FirstSecondChance.cs │ ├── Program.cs │ └── chapter_14_03.csproj ├── chapter_15 ├── chapter_15_01 │ ├── Nullable1.cs │ ├── Nullable2.cs │ ├── Nullable3.cs │ └── chapter_15_01.csproj ├── chapter_15_02 │ ├── InterfaceMembers1.cs │ ├── InterfaceMembers2.cs │ ├── InterfaceMembers3.cs │ ├── InterfaceMembers4.cs │ ├── InterfaceMembers5.cs │ └── chapter_15_02.csproj ├── chapter_15_03 │ ├── RangesIndices1.cs │ ├── RangesIndices2.cs │ ├── RangesIndices3.cs │ ├── RangesIndices4.cs │ └── chapter_15_03.csproj ├── chapter_15_04 │ ├── PatternMatching1.cs │ ├── PatternMatching2.cs │ ├── PatternMatching3.cs │ ├── PatternMatching4.cs │ ├── PatternMatching5.cs │ └── chapter_15_04.csproj ├── chapter_15_05 │ ├── Program.cs │ └── chapter_15_05.csproj ├── chapter_15_06 │ ├── Program.cs │ └── chapter_15_06.csproj ├── chapter_15_07 │ ├── DisposablePattern1.cs │ └── chapter_15_07.csproj ├── chapter_15_08 │ ├── AsyncStreams1.cs │ ├── AsyncStreams2.cs │ ├── AsyncStreams3.cs │ ├── AsyncStreams4.cs │ └── chapter_15_08.csproj ├── chapter_15_09 │ ├── Numbers.cs │ ├── Program.cs │ ├── Undetected.cs │ ├── Vector.cs │ └── chapter_15_09.csproj ├── chapter_15_10 │ ├── NullCoalescing1.cs │ └── chapter_15_10.csproj ├── chapter_15_11 │ ├── Program.cs │ └── chapter_15_11.csproj ├── chapter_15_12 │ ├── Interpolated1.cs │ └── chapter_15_12.csproj ├── chapter_15_13 │ ├── StackAlloc1.cs │ └── chapter_15_13.csproj └── chapter_15_14 │ ├── Program.cs │ └── chapter_15_14.csproj ├── chapter_17 ├── chapter_17_lib │ ├── Rectangle.cs │ └── chapter_17_lib.csproj ├── chapter_17_tests │ ├── DemoTests.cs │ ├── RectangleDataDrivenTests.cs │ ├── RectangleExtensionsTests.cs │ ├── RectangleTests.cs │ └── chapter_17_tests.csproj └── chapter_17_tests_netframework │ ├── App.config │ ├── Properties │ └── AssemblyInfo.cs │ ├── RectangleDataDrivenTests.cs │ ├── TestData.csv │ ├── chapter_17_tests_netframework.csproj │ └── packages.config └── learning_charp8.sln /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs 6 | /src/.vs/learning_charp8 7 | /src/chapter_07/chapter_07_01/obj 8 | /src/chapter_07/chapter_07_01/bin/Debug/netcoreapp2.1 9 | /src/chapter_07/chapter_07_02/obj 10 | /src/chapter_07/chapter_07_02/bin/Debug/netcoreapp2.1 11 | /src/chapter_07/chapter_07_03/obj 12 | /src/chapter_07/chapter_07_03/bin/Debug/netcoreapp2.1 13 | /src/chapter_07/chapter_07_04/obj 14 | /src/chapter_07/chapter_07_04/bin/Debug/netcoreapp2.1 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Learn C# Programming 5 | 6 | By [Marius Bancila](https://github.com/mariusbancila), [Ankit Sharma](https://github.com/AnkitSharma-007), [Raffaele Rialdi](https://github.com/raffaeler) 7 | 8 | Published by [Packt](https://github.com/PacktPublishing) 9 | 10 | 11 | # Structure and code conventions 12 | 13 | The source code is located in the *src* folder. 14 | 15 | For each chapter, there is a subfolder here with the name chapter_*number* (e.g. chapter_01, chapter_02, chapter_03, etc.) 16 | Some chapters are split in multiple projects, one for each topic. For instance: 17 | 18 | * chapter_01\chapter_01 - Hello World program 19 | * chapter_02\chapter_02 - Data types, variables, constants, arrays, nullables, type conversions, operators 20 | * chapter_08\chapter_08_01 - Delegates and Events 21 | * chapter_08\chapter_08_02 - Anonymous methods 22 | * chapter_08\chapter_08_03 - Tuples 23 | * chapter_08\chapter_08_04 - Pattern matching 24 | * chapter_08\chapter_08_05 - Regular expressions 25 | * chapter_08\chapter_08_06 - Extension methods 26 | 27 | The solution file *learning_charp8.sln* contains all these projects together. The projects are .NET Core console apps and target .NET Core 3.1. 28 | 29 | ### Download a free PDF 30 | 31 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
32 |

https://packt.link/free-ebook/9781789805864

-------------------------------------------------------------------------------- /src/EngineLibBase/EngineLibBase.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/EngineLibBase/IEngine.cs: -------------------------------------------------------------------------------- 1 | namespace EngineLibBase 2 | { 3 | public enum EngineStatus { Stopped, Started } 4 | 5 | public interface IEngine 6 | { 7 | EngineStatus Status { get; } 8 | void Start(); 9 | void Stop(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/chapter_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_01 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine("Hello World!"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/chapter_01/chapter_01.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_02/chapter_02.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_03/chapter_03.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.572 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter_04", "chapter_04\chapter_04.csproj", "{A0645FF4-A022-4A49-A82D-67C9E36ABE29}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A0645FF4-A022-4A49-A82D-67C9E36ABE29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A0645FF4-A022-4A49-A82D-67C9E36ABE29}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A0645FF4-A022-4A49-A82D-67C9E36ABE29}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A0645FF4-A022-4A49-A82D-67C9E36ABE29}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {E9F95B08-7DE0-42A1-AB2C-B4A0B3A27889} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/AccessModifiers.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_04 2 | { 3 | #pragma warning disable CS0649 4 | public interface IEngine 5 | { 6 | double Power { get; } 7 | 8 | void Start(); 9 | } 10 | 11 | public class DieselEngine : IEngine 12 | { 13 | private double _power; 14 | public double Power { get { return _power; } } 15 | 16 | public void Start() { } 17 | } 18 | #pragma warning restore CS0649 19 | } 20 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/MassConverters.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_04 2 | { 3 | static class MassConverters 4 | { 5 | public static double PoundToKg(double pounds) 6 | { 7 | return pounds * 0.45359237; 8 | } 9 | 10 | public static double KgToPound(double kgs) 11 | { 12 | return kgs * 2.20462262185; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/Namespaces.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_04 2 | { 3 | class foo1 { } 4 | } 5 | 6 | namespace chapter_04 7 | { 8 | namespace demo 9 | { 10 | class foo2 { } 11 | } 12 | } 13 | 14 | namespace chapter_04.demo 15 | { 16 | class foo3 { } 17 | } 18 | 19 | namespace chapter_04.demo 20 | { 21 | class bar { } 22 | } 23 | 24 | namespace chapter_04.System 25 | { 26 | class Console { } 27 | } -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_04 4 | { 5 | namespace v1 6 | { 7 | struct Point 8 | { 9 | public int x; 10 | public int y; 11 | } 12 | } 13 | 14 | namespace v2 15 | { 16 | struct Point 17 | { 18 | public int X { get; } 19 | public int Y { get; } 20 | 21 | public Point(int x = 0, int y = 0) 22 | { 23 | X = x; 24 | Y = y; 25 | } 26 | } 27 | } 28 | 29 | namespace v3 30 | { 31 | struct Point : IEquatable 32 | { 33 | public int X { get; } 34 | public int Y { get; } 35 | 36 | public Point(int x = 0, int y = 0) 37 | { 38 | X = x; 39 | Y = y; 40 | } 41 | 42 | public bool Equals(Point other) 43 | { 44 | return X == other.X && Y == other.Y; 45 | } 46 | 47 | public override bool Equals(object obj) 48 | { 49 | if (obj is Point other) 50 | { 51 | return this.Equals(other); 52 | } 53 | return false; 54 | } 55 | 56 | public override int GetHashCode() 57 | { 58 | return X.GetHashCode() * 17 + Y.GetHashCode(); 59 | } 60 | } 61 | } 62 | 63 | 64 | namespace v4 65 | { 66 | struct Point 67 | { 68 | public int X { get; } 69 | public int Y { get; } 70 | 71 | public Point(int x = 0, int y = 0) 72 | { 73 | X = x; 74 | Y = y; 75 | } 76 | 77 | public override bool Equals(object obj) 78 | { 79 | if (obj is Point other) 80 | { 81 | return this.Equals(other); 82 | } 83 | return false; 84 | } 85 | 86 | public override int GetHashCode() 87 | { 88 | return X.GetHashCode() * 17 + Y.GetHashCode(); 89 | } 90 | 91 | public static bool operator !=(Point p1, Point p2) 92 | { 93 | return p1.X != p2.X || p1.Y != p2.Y; 94 | } 95 | 96 | public static bool operator ==(Point p1, Point p2) 97 | { 98 | return p1.X == p2.X && p1.Y == p2.Y; 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/Priority.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_04 2 | { 3 | namespace v1 4 | { 5 | enum Priority 6 | { 7 | Low, 8 | Normal, 9 | Important, 10 | Urgent 11 | } 12 | } 13 | 14 | namespace v2 15 | { 16 | enum Priority 17 | { 18 | Low = 0, 19 | Normal = 1, 20 | Important = 2, 21 | Urgent = 3 22 | } 23 | } 24 | 25 | namespace v3 26 | { 27 | enum Priority 28 | { 29 | Low = 10, 30 | Normal, 31 | Important = 20, 32 | Urgent 33 | } 34 | } 35 | 36 | namespace v4 37 | { 38 | enum Priority : byte 39 | { 40 | Low = 10, 41 | Normal, 42 | Important = 20, 43 | Urgent 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/Project.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_04 2 | { 3 | class Project 4 | { 5 | v8.Employee owner; 6 | 7 | public string Name { get; private set; } 8 | 9 | public Project(string name, v8.Employee owner) 10 | { 11 | Name = name; 12 | this.owner = owner; 13 | } 14 | 15 | public ref v8.Employee GetOwner() 16 | { 17 | return ref owner; 18 | } 19 | 20 | public override string ToString() => $"{Name} (Owner={owner.FirstName} {owner.LastName})"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/chapter_04/chapter_04/chapter_04.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_05/chapter_05.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.572 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter_05", "chapter_05\chapter_05.csproj", "{0733AAC8-0CD9-4DA1-BA96-CF9E53BA122F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0733AAC8-0CD9-4DA1-BA96-CF9E53BA122F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0733AAC8-0CD9-4DA1-BA96-CF9E53BA122F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {0733AAC8-0CD9-4DA1-BA96-CF9E53BA122F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {0733AAC8-0CD9-4DA1-BA96-CF9E53BA122F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5F524720-00A4-42E6-9513-0D2E7BE22477} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/chapter_05/chapter_05/Complex.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_05 2 | { 3 | public struct Complex 4 | { 5 | public double Real { get; private set; } 6 | public double Imaginary { get; private set; } 7 | 8 | public Complex(double real = 0, double imaginary = 0) 9 | { 10 | Real = real; 11 | Imaginary = imaginary; 12 | } 13 | 14 | public override string ToString() => $"{Real}i + {Imaginary}"; 15 | 16 | public static Complex operator +(Complex number1, Complex number2) 17 | { 18 | return new Complex() 19 | { 20 | Real = number1.Real + number2.Real, 21 | Imaginary = number1.Imaginary + number2.Imaginary 22 | }; 23 | } 24 | 25 | public static Complex operator -(Complex number1, Complex number2) 26 | { 27 | return new Complex() 28 | { 29 | Real = number1.Real - number2.Real, 30 | Imaginary = number1.Imaginary - number2.Imaginary 31 | }; 32 | } 33 | 34 | public static bool operator ==(Complex number1, Complex number2) 35 | { 36 | return number1.Real.Equals(number2.Real) && 37 | number1.Imaginary.Equals(number2.Imaginary); 38 | } 39 | 40 | public static bool operator !=(Complex number1, Complex number2) 41 | { 42 | return !number1.Real.Equals(number2.Real) || 43 | !number1.Imaginary.Equals(number2.Imaginary); 44 | } 45 | 46 | public override bool Equals(object obj) 47 | { 48 | return Real.Equals(((Complex)obj).Real) && 49 | Imaginary.Equals(((Complex)obj).Imaginary); 50 | } 51 | 52 | public override int GetHashCode() 53 | { 54 | return Real.GetHashCode() * 17 + Imaginary.GetHashCode(); 55 | } 56 | 57 | public static Complex operator ++(Complex number) 58 | { 59 | return new Complex(number.Real + 1, number.Imaginary); 60 | } 61 | 62 | public static Complex operator --(Complex number) 63 | { 64 | return new Complex(number.Real - 1, number.Imaginary); 65 | } 66 | } 67 | 68 | namespace v2 69 | { 70 | public class Complex 71 | { 72 | public double Real { get; private set; } 73 | public double Imaginary { get; private set; } 74 | 75 | public Complex(double real = 0, double imaginary = 0) 76 | { 77 | Real = real; 78 | Imaginary = imaginary; 79 | } 80 | 81 | public override string ToString() => $"{Real}i + {Imaginary}"; 82 | 83 | public static Complex operator ++(Complex number) 84 | { 85 | // WRONG implementation 86 | number.Real++; 87 | return number; 88 | } 89 | } 90 | } 91 | 92 | namespace v3 93 | { 94 | public class Complex 95 | { 96 | public double Real { get; private set; } 97 | public double Imaginary { get; private set; } 98 | 99 | public Complex(double real = 0, double imaginary = 0) 100 | { 101 | Real = real; 102 | Imaginary = imaginary; 103 | } 104 | 105 | public override string ToString() => $"{Real}i + {Imaginary}"; 106 | 107 | public static Complex operator ++(Complex number) 108 | { 109 | return new Complex(number.Real + 1, number.Imaginary); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/chapter_05/chapter_05/Employee.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_05 2 | { 3 | public class Employee 4 | { 5 | private string name; 6 | private double salary; 7 | 8 | public string Name 9 | { 10 | get { return name; } 11 | set { name = value; } 12 | } 13 | 14 | public double Salary 15 | { 16 | get { return salary; } 17 | } 18 | 19 | public Employee(string name, double salary) 20 | { 21 | this.name = name; 22 | this.salary = salary; 23 | } 24 | 25 | public void GiveRaise(double percent) 26 | { 27 | salary *= (1.0 + percent / 100.0); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/chapter_05/chapter_05/chapter_05.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.572 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter_06", "chapter_06\chapter_06.csproj", "{8FBB6318-D5D9-40AF-8005-27674BF75986}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8FBB6318-D5D9-40AF-8005-27674BF75986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {8FBB6318-D5D9-40AF-8005-27674BF75986}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {8FBB6318-D5D9-40AF-8005-27674BF75986}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {8FBB6318-D5D9-40AF-8005-27674BF75986}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {892237B8-AE84-4A6F-91F2-F6CBE1942C85} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/CompareObjects.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_06 2 | { 3 | class CompareObjects 4 | { 5 | public bool Compare(T input1, T input2) 6 | { 7 | return input1.Equals(input2); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/ConflictingGenerics.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_06 2 | { 3 | class ConflictingGenerics 4 | { 5 | public void DoSomething(T arg) // warning 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/GenericDemo.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_06 2 | { 3 | public class GenericDemo 4 | { 5 | public T Value { get; private set; } 6 | 7 | public GenericDemo(T value) 8 | { 9 | Value = value; 10 | } 11 | 12 | public override string ToString() => $"{typeof(T)} : {Value}"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/IMultiVariant.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_06 2 | { 3 | interface IMultiVariant 4 | { 5 | T Make(); 6 | void Take(U arg); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/Pair.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_06 2 | { 3 | class Pair 4 | { 5 | public T Item1 { get; private set; } 6 | public U Item2 { get; private set; } 7 | 8 | public Pair(T item1, U item2) 9 | { 10 | Item1 = item1; 11 | Item2 = item2; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_06 4 | { 5 | namespace v1 6 | { 7 | struct Point 8 | { 9 | public T X { get; } 10 | public T Y { get; } 11 | 12 | public Point(T x, T y) 13 | { 14 | X = x; 15 | Y = y; 16 | } 17 | } 18 | } 19 | 20 | namespace v2 21 | { 22 | struct Point 23 | where T : struct, 24 | IComparable, IComparable, 25 | IConvertible, 26 | IEquatable, 27 | IFormattable 28 | { 29 | public T X { get; } 30 | public T Y { get; } 31 | 32 | public Point(T x, T y) 33 | { 34 | X = x; 35 | Y = y; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/RestrictedDictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace chapter_06 4 | { 5 | class RestrictedDictionary : Dictionary> 6 | where TKey : System.Enum 7 | where TValue : class, new() 8 | { 9 | public T Make(TKey key) where T : TValue, new() 10 | { 11 | var value = new T(); 12 | if (!TryGetValue(key, out List list)) 13 | { 14 | Add(key, new List() { value }); 15 | } 16 | else 17 | { 18 | list.Add(value); 19 | } 20 | 21 | return value; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/chapter_06/chapter_06/chapter_06.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_07/chapter_07.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/Program.cs: -------------------------------------------------------------------------------- 1 | namespace chapter_08_01 2 | { 3 | class Program 4 | { 5 | static void Main(string[] args) 6 | { 7 | version1.Example.Execute(); 8 | version2.Example.Execute(); 9 | version3.Example.Execute(); 10 | version4.Example.Execute(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/chapter_08_01.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/version1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_08_01.version1 4 | { 5 | public enum Status { Started, Stopped } 6 | 7 | public delegate void StatusChange(Status status); 8 | 9 | public class Engine 10 | { 11 | private StatusChange statusChangeHandler; 12 | 13 | public void RegisterStatusChangeHandler(StatusChange handler) 14 | { 15 | statusChangeHandler = handler; 16 | } 17 | 18 | public void Start() 19 | { 20 | if (statusChangeHandler != null) 21 | statusChangeHandler(Status.Started); 22 | } 23 | 24 | public void Stop() 25 | { 26 | if (statusChangeHandler != null) 27 | statusChangeHandler(Status.Stopped); 28 | } 29 | } 30 | 31 | class Example 32 | { 33 | public static void Execute() 34 | { 35 | Engine engine = new Engine(); 36 | engine.RegisterStatusChangeHandler(OnEngineStatusChanged); 37 | 38 | engine.Start(); 39 | 40 | engine.Stop(); 41 | } 42 | 43 | private static void OnEngineStatusChanged(Status status) 44 | { 45 | Console.WriteLine($"Engine is now {status}"); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/version2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace chapter_08_01.version2 5 | { 6 | public enum Status { Started, Stopped } 7 | 8 | public delegate void StatusChange(Status status); 9 | 10 | public class Engine 11 | { 12 | private StatusChange statusChangeHandler; 13 | 14 | public void RegisterStatusChangeHandler(StatusChange handler) 15 | { 16 | statusChangeHandler += handler; 17 | } 18 | 19 | public void UnregisterStatusChangeHandler(StatusChange handler) 20 | { 21 | statusChangeHandler -= handler; 22 | } 23 | 24 | public void Start() 25 | { 26 | statusChangeHandler?.Invoke(Status.Started); 27 | } 28 | 29 | public void Stop() 30 | { 31 | statusChangeHandler?.Invoke(Status.Stopped); 32 | } 33 | } 34 | 35 | class Example 36 | { 37 | public static void Execute() 38 | { 39 | Engine engine = new Engine(); 40 | engine.RegisterStatusChangeHandler(OnEngineStatusChanged); 41 | engine.RegisterStatusChangeHandler(OnEngineStatusChanged2); 42 | 43 | engine.Start(); 44 | engine.Stop(); 45 | 46 | engine.UnregisterStatusChangeHandler(OnEngineStatusChanged2); 47 | 48 | engine.Start(); 49 | } 50 | 51 | private static void OnEngineStatusChanged(Status status) 52 | { 53 | Console.WriteLine($"Engine is now {status}"); 54 | } 55 | 56 | private static void OnEngineStatusChanged2(Status status) 57 | { 58 | File.AppendAllText( 59 | @"c:\temp\engine.log", 60 | $"Engine is now {status}\n"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/version3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace chapter_08_01.version3 5 | { 6 | public enum Status { Started, Stopped } 7 | 8 | public delegate void StatusChange(Status status); 9 | 10 | public class Engine 11 | { 12 | public event StatusChange StatusChanged; 13 | 14 | public void Start() 15 | { 16 | StatusChanged?.Invoke(Status.Started); 17 | } 18 | 19 | public void Stop() 20 | { 21 | StatusChanged?.Invoke(Status.Stopped); 22 | } 23 | } 24 | 25 | class Example 26 | { 27 | public static void Execute() 28 | { 29 | Engine engine = new Engine(); 30 | engine.StatusChanged += OnEngineStatusChanged; 31 | engine.StatusChanged += status => Console.WriteLine($"Engine is now {status}"); 32 | 33 | engine.Start(); 34 | engine.Stop(); 35 | 36 | engine.StatusChanged -= OnEngineStatusChanged; 37 | 38 | engine.Start(); 39 | } 40 | 41 | private static void OnEngineStatusChanged(Status status) 42 | { 43 | File.AppendAllText( 44 | @"c:\temp\engine.log", 45 | $"Engine is now {status}\n"); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_01/version4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace chapter_08_01.version4 5 | { 6 | public enum Status { Started, Stopped } 7 | 8 | public class EngineEventArgs : EventArgs 9 | { 10 | public Status Status { get; private set; } 11 | 12 | public EngineEventArgs(Status s) 13 | { 14 | Status = s; 15 | } 16 | } 17 | 18 | public delegate void StatusChange(object sender, EngineEventArgs args); 19 | 20 | public class Engine 21 | { 22 | public event StatusChange StatusChanged; 23 | 24 | public void Start() 25 | { 26 | StatusChanged?.Invoke(this, new EngineEventArgs(Status.Started)); 27 | } 28 | 29 | public void Stop() 30 | { 31 | StatusChanged?.Invoke(this, new EngineEventArgs(Status.Stopped)); 32 | } 33 | } 34 | 35 | class Example 36 | { 37 | public static void Execute() 38 | { 39 | Engine engine = new Engine(); 40 | engine.StatusChanged += OnEngineStatusChanged; 41 | engine.StatusChanged += (s, args) => Console.WriteLine($"Engine is now {args.Status}"); 42 | 43 | engine.Start(); 44 | engine.Stop(); 45 | 46 | engine.StatusChanged -= OnEngineStatusChanged; 47 | 48 | engine.Start(); 49 | } 50 | 51 | private static void OnEngineStatusChanged(object sender, EngineEventArgs args) 52 | { 53 | File.AppendAllText( 54 | @"c:\temp\engine.log", 55 | $"Engine is now {args.Status}\n"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_08_02 4 | { 5 | class Engine 6 | { 7 | public string Name { get; } 8 | public int Capacity { get; } 9 | public double Power { get; } 10 | 11 | public Engine(string name, int capacity, double power) 12 | { 13 | Name = name; 14 | Capacity = capacity; 15 | Power = power; 16 | } 17 | } 18 | 19 | class Program 20 | { 21 | static void Main(string[] args) 22 | { 23 | { 24 | var o = new { Name = "M270 Turbo", Capacity = 1600, Power = 75.0 }; 25 | Console.WriteLine($"{o.Name} {o.Capacity / 1000.0}l {o.Power}kW"); 26 | } 27 | 28 | { 29 | var e = new Engine("M270 Turbo", 1600, 75.0); 30 | var o = new { e.Name, e.Power }; 31 | Console.WriteLine($"{o.Name} {o.Power}kW"); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_02/chapter_08_02.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_03/chapter_08_03.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_04/chapter_08_04.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_05/chapter_08_05.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_06/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using chapter_08_06.Extensions; 4 | 5 | namespace chapter_08_06 6 | { 7 | namespace Simple 8 | { 9 | static class StringExtensions 10 | { 11 | public static string Reverse(string s) 12 | { 13 | var charArray = s.ToCharArray(); 14 | Array.Reverse(charArray); 15 | return new string(charArray); 16 | } 17 | } 18 | } 19 | 20 | namespace Extensions 21 | { 22 | static class StringExtensions 23 | { 24 | public static string Reverse(this string s) 25 | { 26 | var charArray = s.ToCharArray(); 27 | Array.Reverse(charArray); 28 | return new string(charArray); 29 | } 30 | } 31 | 32 | static class ExceptionExtensions 33 | { 34 | public static string AllMessages( 35 | this Exception exception, 36 | bool reverse = false) 37 | { 38 | var messages = new List(); 39 | var ex = exception; 40 | while (ex != null) 41 | { 42 | messages.Add(ex.Message); 43 | ex = ex.InnerException; 44 | } 45 | 46 | if (reverse) messages.Reverse(); 47 | 48 | return string.Join(Environment.NewLine, messages); 49 | } 50 | } 51 | } 52 | 53 | class Program 54 | { 55 | static void Main(string[] args) 56 | { 57 | { 58 | var text = "demo"; 59 | var result = Simple.StringExtensions.Reverse(text); 60 | } 61 | 62 | { 63 | var text = "demo"; 64 | var result = text.Reverse(); 65 | } 66 | 67 | { 68 | var exception = 69 | new InvalidOperationException( 70 | "An invalid operation occurred", 71 | new NotSupportedException( 72 | "The operation is not supported", 73 | new InvalidCastException( 74 | "Cannot apply cast!"))); 75 | 76 | Console.WriteLine(exception.AllMessages()); 77 | Console.WriteLine(exception.AllMessages(true)); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/chapter_08/chapter_08_06/chapter_08_06.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_09_01 4 | { 5 | class Engine 6 | { 7 | public string Name { get; } 8 | public int Capacity { get; } 9 | public double Power { get; } 10 | 11 | public Engine(string name, int capacity, double power) 12 | { 13 | Name = name; 14 | Capacity = capacity; 15 | Power = power; 16 | } 17 | } 18 | 19 | class Program 20 | { 21 | static void Main(string[] args) 22 | { 23 | var engine = new Engine("M270 Turbo", 1600, 75.0); 24 | Console.WriteLine($"Generation of engine: {GC.GetGeneration(engine)}"); 25 | 26 | Console.WriteLine($"Estimated heap size: {GC.GetTotalMemory(false)}"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_01/chapter_09_01.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace chapter_09_02 5 | { 6 | class ResourceWrapper 7 | { 8 | // constructor 9 | ResourceWrapper() 10 | { 11 | // construct the object 12 | } 13 | 14 | // finalizer 15 | ~ResourceWrapper() 16 | { 17 | // release unmanaged resources 18 | } 19 | } 20 | 21 | public class HandleWrapper 22 | { 23 | [DllImport("kernel32.dll", SetLastError = true)] 24 | static extern bool CloseHandle(IntPtr hHandle); 25 | 26 | public IntPtr Handle { get; private set; } 27 | 28 | public HandleWrapper(IntPtr ptr) 29 | { 30 | Handle = ptr; 31 | } 32 | 33 | ~HandleWrapper() 34 | { 35 | if (Handle != default) 36 | CloseHandle(Handle); 37 | } 38 | } 39 | 40 | class Program 41 | { 42 | static void Main(string[] args) 43 | { 44 | Console.WriteLine("Hello World!"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_02/chapter_09_02.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_03/chapter_09_03.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_04/chapter_09_04.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_05/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_09_05 4 | { 5 | unsafe struct Node 6 | { 7 | public int Value; 8 | public Node* Left; 9 | public Node* Right; 10 | } 11 | 12 | struct Node2 13 | { 14 | public int Value; 15 | public unsafe Node2* Left; 16 | public unsafe Node2* Right; 17 | } 18 | 19 | class Color 20 | { 21 | public byte Alpha; 22 | public byte Red; 23 | public byte Green; 24 | public byte Blue; 25 | 26 | public Color(byte a, byte r, byte g, byte b) 27 | { 28 | Alpha = a; 29 | Red = r; 30 | Green = g; 31 | Blue = b; 32 | } 33 | } 34 | 35 | class Program 36 | { 37 | static unsafe void Increment(int* value) 38 | { 39 | *value += 1; 40 | } 41 | 42 | static void SetTransparency(Color color, double value) 43 | { 44 | unsafe 45 | { 46 | fixed (byte* alpha = &color.Alpha) 47 | { 48 | *alpha = (byte)(value * 255); 49 | } 50 | } 51 | } 52 | 53 | static unsafe void AllocArrayExample(int size) 54 | { 55 | int* arr = stackalloc int[size]; 56 | for (int i = 1; i <= size; ++i) 57 | arr[i] = i; 58 | } 59 | 60 | static void SizeOfExample() 61 | { 62 | unsafe 63 | { 64 | Console.WriteLine($"Pointer size: {sizeof(int*)}"); 65 | } 66 | } 67 | 68 | static void Main(string[] args) 69 | { 70 | int value = 42; 71 | unsafe 72 | { 73 | int* p = &value; 74 | *p += 1; 75 | } 76 | Console.WriteLine(value); 77 | 78 | unsafe 79 | { 80 | Increment(&value); // OK 81 | } 82 | 83 | // Increment(&value); // error 84 | 85 | Color color = new Color(255, 255, 0, 0); 86 | SetTransparency(color, .5); 87 | 88 | unsafe 89 | { 90 | AllocArrayExample(32); 91 | } 92 | 93 | SizeOfExample(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/chapter_09/chapter_09_05/chapter_09_05.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | true 10 | false 11 | AnyCPU 12 | 13 | 14 | 15 | true 16 | true 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_10_01 4 | { 5 | namespace version1 6 | { 7 | struct Rectangle 8 | { 9 | public int Left; 10 | public int Right; 11 | public int Top; 12 | public int Bottom; 13 | 14 | public int Width { get { return Right - Left; } } 15 | public int Height { get { return Bottom - Top; } } 16 | 17 | public Rectangle(int l, int t, int r, int b) 18 | { 19 | Left = l; 20 | Top = t; 21 | Right = r; 22 | Bottom = b; 23 | } 24 | 25 | public void Inflate(int l, int t, int r, int b) 26 | { 27 | Left -= l; 28 | Right += r; 29 | Top -= t; 30 | Bottom += b; 31 | } 32 | } 33 | 34 | static class Helpers 35 | { 36 | public static void Inflate(ref Rectangle rect, int l, int t, int r, int b) 37 | { 38 | rect.Left -= l; 39 | rect.Right += r; 40 | rect.Top -= t; 41 | rect.Bottom += b; 42 | } 43 | } 44 | } 45 | 46 | namespace version2 47 | { 48 | struct Rectangle 49 | { 50 | public readonly int Left; 51 | public readonly int Right; 52 | public readonly int Top; 53 | public readonly int Bottom; 54 | 55 | public int Width { get { return Right - Left; } } 56 | public int Height { get { return Bottom - Top; } } 57 | 58 | public Rectangle(int l, int t, int r, int b) 59 | { 60 | Left = l; 61 | Top = t; 62 | Right = r; 63 | Bottom = b; 64 | } 65 | } 66 | 67 | static class Helpers 68 | { 69 | public static Rectangle Inflate(Rectangle rect, int l, int t, int r, int b) 70 | { 71 | return new Rectangle(rect.Left - l, 72 | rect.Right + r, 73 | rect.Top - t, 74 | rect.Bottom + b); 75 | } 76 | } 77 | } 78 | 79 | class Program 80 | { 81 | static void Main(string[] args) 82 | { 83 | { 84 | var r = new version1.Rectangle(10, 10, 30, 20); 85 | r.Left -= 5; 86 | r.Right += 5; 87 | 88 | r.Inflate(5, 0, 5, 0); 89 | 90 | version1.Helpers.Inflate(ref r, 5, 0, 5, 0); 91 | } 92 | 93 | { 94 | var r = new version2.Rectangle(10, 10, 30, 20); 95 | r = version2.Helpers.Inflate(r, 5, 0, 5, 0); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_01/chapter_10_01.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter_10_02 4 | { 5 | namespace delegates 6 | { 7 | public delegate int Combine(int a, int b); 8 | 9 | class Math 10 | { 11 | public static int Add(int a, int b) { return a + b; } 12 | public static int Sub(int a, int b) { return a - b; } 13 | public static int Mul(int a, int b) { return a * b; } 14 | } 15 | 16 | class Util 17 | { 18 | public static int Apply(int a, int b, Combine f) 19 | { 20 | return f(a, b); 21 | } 22 | } 23 | } 24 | 25 | namespace functions 26 | { 27 | class Math 28 | { 29 | public static int Add(int a, int b) { return a + b; } 30 | public static int Sub(int a, int b) { return a - b; } 31 | public static int Mul(int a, int b) { return a * b; } 32 | } 33 | 34 | class Util 35 | { 36 | public static T Apply(T a, T b, Func f) 37 | { 38 | return f(a, b); 39 | } 40 | 41 | public static Func ApplyReverse(Func f) 42 | { 43 | return delegate (T a, T b) { return f(b, a); }; 44 | } 45 | 46 | public static T Apply(T a, T b, Func f, Action log) 47 | { 48 | var r = f(a, b); 49 | 50 | log?.Invoke($"{f.Method.Name}({a},{b}) = {r}"); 51 | 52 | return r; 53 | } 54 | } 55 | } 56 | 57 | class Program 58 | { 59 | static void Main(string[] args) 60 | { 61 | { 62 | var s = delegates.Util.Apply(2, 3, delegates.Math.Add); 63 | var p = delegates.Util.Apply(2, 3, delegates.Math.Mul); 64 | } 65 | 66 | { 67 | var s = functions.Util.Apply(2, 3, functions.Math.Add); 68 | var p = functions.Util.Apply(2, 3, functions.Math.Mul); 69 | } 70 | 71 | { 72 | var s = functions.Util.Apply(2, 3, functions.Math.Add, Console.WriteLine); 73 | var p = functions.Util.Apply(2, 3, functions.Math.Mul, Console.WriteLine); 74 | } 75 | 76 | { 77 | var s = functions.Util.ApplyReverse(functions.Math.Add)(2, 3); 78 | var d = functions.Util.ApplyReverse(functions.Math.Sub)(2, 3); 79 | } 80 | 81 | { 82 | var s = functions.Util.Apply(2, 3, (a, b) => a + b); 83 | var d = functions.Util.Apply(2, 3, (a, b) => a - b); 84 | var p = functions.Util.Apply(2, 3, (a, b) => a * b); 85 | } 86 | 87 | { 88 | Func, int> apply = (a, b, f) => f(a, b); 89 | 90 | var s = apply(2, 3, (a, b) => a + b); 91 | var d = apply(2, 3, (a, b) => a - b); 92 | var p = apply(2, 3, (a, b) => a * b); 93 | } 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_02/chapter_10_02.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_03/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter_10_03 6 | { 7 | public class Form 8 | { 9 | public Form() { } 10 | } 11 | 12 | public delegate void ControlEvent(object sender, EventArgs args); 13 | 14 | public class Button 15 | { 16 | public event ControlEvent Click; 17 | } 18 | 19 | public partial class MyForm : Form 20 | { 21 | private Button myButton = new Button(); 22 | 23 | private void InitializeComponent() { } 24 | } 25 | 26 | public partial class MyForm : Form 27 | { 28 | public MyForm() 29 | { 30 | InitializeComponent(); 31 | 32 | myButton.Click += async (sender, e) => 33 | { 34 | await ExampleMethodAsync(); 35 | }; 36 | } 37 | 38 | private async Task ExampleMethodAsync() 39 | { 40 | // a time-consuming action 41 | await Task.Delay(1000); 42 | } 43 | } 44 | 45 | class Foo 46 | { 47 | public int Data { get; private set; } 48 | 49 | public Foo(int value) 50 | { 51 | Data = value; 52 | } 53 | 54 | public void Scramble(int value, int iterations) 55 | { 56 | Func apply = (i) => Data ^ i + value; 57 | for (int i = 0; i < iterations; ++i) 58 | Data = apply(i); 59 | } 60 | } 61 | 62 | class Program 63 | { 64 | static void Main(string[] args) 65 | { 66 | { 67 | bool IsOdd(int x) { return x % 2 == 1; } 68 | var list = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 69 | list.RemoveAll(IsOdd); 70 | } 71 | 72 | { 73 | var list = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 74 | list.RemoveAll(delegate (int x) { return x % 2 == 1; }); 75 | } 76 | 77 | { 78 | var list = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 79 | list.RemoveAll(x => x % 2 == 1); 80 | } 81 | 82 | { 83 | var list = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 84 | list.RemoveAll(x => { return x % 2 == 1; }); 85 | } 86 | 87 | { 88 | var f = new Foo(42); 89 | f.Scramble(991, 13); 90 | Console.WriteLine(f.Data); 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_03/chapter_10_03.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_04/chapter_10_04.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_10/chapter_10_05/chapter_10_05.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_11/EngineLib/Engine.cs: -------------------------------------------------------------------------------- 1 | using EngineLibBase; 2 | 3 | namespace EngineLib 4 | { 5 | public class Engine : IEngine 6 | { 7 | public string Name { get; } 8 | public int Capacity { get; } 9 | public double Power { get; } 10 | public EngineStatus Status { get; private set; } 11 | 12 | public Engine(string name, int capacity, double power) 13 | { 14 | Name = name; 15 | Capacity = capacity; 16 | Power = power; 17 | Status = EngineStatus.Stopped; 18 | } 19 | 20 | public void Start() 21 | { 22 | Status = EngineStatus.Started; 23 | } 24 | 25 | public void Stop() 26 | { 27 | Status = EngineStatus.Stopped; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/chapter_11/EngineLib/EngineLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace chapter_11_01 6 | { 7 | public enum EngineStatus { Stopped, Started } 8 | 9 | public class Engine 10 | { 11 | public string Name { get; } 12 | public int Capacity { get; } 13 | public double Power { get; } 14 | public EngineStatus Status { get; private set; } 15 | 16 | public Engine(string name, int capacity, double power) 17 | { 18 | Name = name; 19 | Capacity = capacity; 20 | Power = power; 21 | Status = EngineStatus.Stopped; 22 | } 23 | 24 | public void Start() 25 | { 26 | Status = EngineStatus.Started; 27 | } 28 | 29 | public void Stop() 30 | { 31 | Status = EngineStatus.Stopped; 32 | } 33 | } 34 | 35 | class Program 36 | { 37 | static void Main(string[] args) 38 | { 39 | var type = typeof(Engine); 40 | 41 | Console.WriteLine(type.Name); 42 | 43 | var properties = type.GetProperties(); 44 | foreach(var p in properties) 45 | { 46 | Console.WriteLine($"{p.Name} ({p.PropertyType.Name})"); 47 | } 48 | 49 | var methods = type.GetMethods( 50 | BindingFlags.Public| 51 | BindingFlags.Instance| 52 | BindingFlags.DeclaredOnly); 53 | foreach(var m in methods) 54 | { 55 | var parameters = string.Join( 56 | ',', 57 | m.GetParameters() 58 | .Select(p => $"{p.ParameterType.Name} {p.Name}")); 59 | 60 | Console.WriteLine($"{m.ReturnType.Name} {m.Name} ({parameters})"); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_01/chapter_11_01.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace chapter_11_02 7 | { 8 | class Program 9 | { 10 | static void DisplayType(Assembly assembly) 11 | { 12 | if (assembly != null) 13 | { 14 | var type = assembly.GetType("EngineLib.Engine"); 15 | if (type != null) 16 | { 17 | var properties = type.GetProperties(); 18 | foreach (var p in properties) 19 | { 20 | Console.WriteLine($"{p.Name} ({p.PropertyType.Name})"); 21 | } 22 | } 23 | } 24 | } 25 | 26 | static void Main(string[] args) 27 | { 28 | //var assembly = Assembly.Load("EngineLib"); 29 | 30 | //var assembly = Assembly.Load(@"EngineLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); 31 | 32 | //var assemblyName = new AssemblyName() 33 | //{ 34 | // Name = "EngineLib", 35 | // Version = new Version(1,0,0,0), 36 | // CultureInfo = null, 37 | // CodeBase = Directory.GetCurrentDirectory() 38 | //}; 39 | 40 | //var assembly = Assembly.Load(assemblyName); 41 | 42 | //var assembly = Assembly.Load(@"WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); 43 | 44 | var assembly = Assembly.LoadFrom("EngineLib.dll"); 45 | 46 | Console.WriteLine( 47 | $@"Name: {assembly.GetName().FullName} 48 | Files: {string.Join( 49 | ',', 50 | assembly.GetFiles().Select( 51 | s=>Path.GetFileName(s.Name)))} 52 | Refs: {string.Join( 53 | ',', 54 | assembly.GetReferencedAssemblies().Select( 55 | n=>n.Name))}"); 56 | 57 | DisplayType(assembly); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_02/chapter_11_02.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_03/Program.cs: -------------------------------------------------------------------------------- 1 | using EngineLibBase; 2 | using System; 3 | using System.Reflection; 4 | 5 | namespace chapter_11_03 6 | { 7 | class Program 8 | { 9 | static void Example1() 10 | { 11 | var assembly = Assembly.LoadFrom("EngineLib.dll"); 12 | 13 | if (assembly != null) 14 | { 15 | var type = assembly.GetType("EngineLib.Engine"); 16 | object engine = assembly.CreateInstance( 17 | "EngineLib.Engine", 18 | true, 19 | BindingFlags.CreateInstance, 20 | null, 21 | new object[] { "M270 Turbo", 1600, 75.0 }, 22 | null, 23 | null); 24 | 25 | /* 26 | object engine = Activator.CreateInstance( 27 | type, 28 | new object[] { "M270 Turbo", 1600, 75.0 }); 29 | */ 30 | 31 | var pi = type.GetProperty("Status"); 32 | if (pi != null) 33 | Console.WriteLine(pi.GetValue(engine)); 34 | 35 | var mi = type.GetMethod("Start"); 36 | if (mi != null) 37 | mi.Invoke(engine, null); 38 | 39 | if (pi != null) 40 | Console.WriteLine(pi.GetValue(engine)); 41 | } 42 | } 43 | 44 | static void Example2() 45 | { 46 | var assembly = Assembly.LoadFrom("EngineLib.dll"); 47 | 48 | if (assembly != null) 49 | { 50 | var type = assembly.GetType("EngineLib.Engine"); 51 | var engine = (IEngine)Activator.CreateInstance( 52 | type, 53 | new object[] { "M270 Turbo", 1600, 75.0 }); 54 | 55 | Console.WriteLine(engine.Status); 56 | engine.Start(); 57 | Console.WriteLine(engine.Status); 58 | } 59 | } 60 | 61 | static void Main(string[] args) 62 | { 63 | Example1(); 64 | Example2(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_03/chapter_11_03.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_04/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Reflection; 5 | 6 | namespace chapter_11_04 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | { 13 | dynamic i = 42; 14 | dynamic s = "42"; 15 | dynamic d = 42.0; 16 | dynamic l = new List { 42 }; 17 | 18 | l.Add(43); // OK 19 | 20 | try 21 | { 22 | s.Add(44); // runtime exception 23 | // RuntimeBinderException: 'string' does not contain a definition for 'Add' 24 | } 25 | catch (Exception ex) 26 | { 27 | Console.WriteLine(ex.Message); 28 | } 29 | } 30 | 31 | { 32 | var assembly = Assembly.LoadFrom("EngineLib.dll"); 33 | 34 | if (assembly != null) 35 | { 36 | var type = assembly.GetType("EngineLib.Engine"); 37 | 38 | dynamic engine = Activator.CreateInstance( 39 | type, 40 | new object[] { "M270 Turbo", 1600, 75.0 }); 41 | 42 | Console.WriteLine(engine.Status); 43 | engine.Start(); 44 | Console.WriteLine(engine.Status); 45 | } 46 | } 47 | 48 | { 49 | dynamic excel = Activator.CreateInstance( 50 | Type.GetTypeFromProgID("Excel.Application.16")); 51 | if (excel != null) 52 | { 53 | excel.Visible = true; 54 | 55 | dynamic workBook = excel.Workbooks.Add(); 56 | dynamic workSheet = excel.ActiveWorkbook.ActiveSheet; 57 | 58 | workSheet.Cells[1, 1] = "ID"; 59 | workSheet.Cells[1, 2] = "Name"; 60 | workSheet.Cells[2, 1] = "1"; 61 | workSheet.Cells[2, 2] = "One"; 62 | workSheet.Cells[3, 1] = "2"; 63 | workSheet.Cells[3, 2] = "Two"; 64 | 65 | workBook.SaveAs("d:\\demo.xls", 66 | Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal, 67 | AccessMode: Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive); 68 | 69 | workBook.Close(true); 70 | excel.Quit(); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_04/chapter_11_04.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/chapter_11/chapter_11_05/chapter_11_05.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_01/CreateThread1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace chapter_12_01 7 | { 8 | public class CreateThread1 9 | { 10 | public void Run() 11 | { 12 | Console.WriteLine("Start primes"); 13 | PrintThreadInfo(Thread.CurrentThread); 14 | var t1 = new Thread(Worker); 15 | //t1.IsBackground = true; // try with/without this line 16 | t1.Start(); 17 | Console.WriteLine("Primes calculation is happening in background"); 18 | } 19 | 20 | private void Worker(object param) 21 | { 22 | PrintThreadInfo(Thread.CurrentThread); 23 | foreach (var n in new Primes(1000000)) 24 | { 25 | Thread.Sleep(100); 26 | } 27 | Console.WriteLine("Computation ended!"); 28 | } 29 | 30 | private void PrintThreadInfo(Thread t) 31 | { 32 | var sb = new StringBuilder(); 33 | var state = t.ThreadState; 34 | sb.Append($"Id:{t.ManagedThreadId} Name:{t.Name} State:{state} "); 35 | if ((state & (ThreadState.Stopped | ThreadState.Unstarted)) == 0) 36 | { 37 | sb.Append($"Priority:{t.Priority} IsBackground:{t.IsBackground}"); 38 | } 39 | 40 | Console.WriteLine(sb.ToString()); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_01/FileWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net.Http; 5 | using System.Net.WebSockets; 6 | using System.Text; 7 | using System.Threading; 8 | 9 | 10 | namespace chapter_12_01 11 | { 12 | public class FileWatcher 13 | { 14 | private FileSystemWatcher _watcher; 15 | public void Run() 16 | { 17 | var path = Path.GetFullPath("."); 18 | Console.WriteLine($"Observing changes in path: {path}"); 19 | _watcher = new FileSystemWatcher(path, "*.txt"); 20 | _watcher.Created += Watcher_Created; 21 | _watcher.Deleted += Watcher_Deleted; 22 | Console.WriteLine($"TID: {Thread.CurrentThread.ManagedThreadId}"); 23 | _watcher.EnableRaisingEvents = true; 24 | } 25 | 26 | private void Watcher_Deleted(object sender, FileSystemEventArgs e) 27 | { 28 | Console.WriteLine($"Deleted occurred in TID: {Thread.CurrentThread.ManagedThreadId}"); 29 | } 30 | 31 | private void Watcher_Created(object sender, FileSystemEventArgs e) 32 | { 33 | Console.WriteLine($"Created occurred in TID: {Thread.CurrentThread.ManagedThreadId}"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_01/Primes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace chapter_12_01 7 | { 8 | public class Primes : IEnumerable 9 | { 10 | public Primes(long Max = long.MaxValue) 11 | { 12 | this.Max = Max; 13 | } 14 | 15 | public long Max { get; private set; } 16 | 17 | IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); 18 | 19 | public IEnumerator GetEnumerator() 20 | { 21 | yield return 1; 22 | bool bFlag; 23 | long start = 2; 24 | while (start < Max) 25 | { 26 | bFlag = false; 27 | var number = start; 28 | for (int i = 2; i < number; i++) 29 | { 30 | if (number % i == 0) 31 | { 32 | bFlag = true; 33 | break; 34 | } 35 | } 36 | 37 | if (!bFlag) 38 | { 39 | yield return number; 40 | } 41 | start++; 42 | } 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | 9 | namespace chapter_12_01 10 | { 11 | class Program 12 | { 13 | [DllImport("Kernel32.dll")] 14 | private static extern int GetCurrentThreadId(); 15 | 16 | static void Main(string[] args) 17 | { 18 | //PrintIds(); 19 | //UsingFileWatcher1(); 20 | //UsingBlockingPrimes(); 21 | //new CreateThread1().Run(); 22 | //new CreateThread2().Run1(); 23 | //new CreateThread2().Run2(); 24 | //new CreateThread2().Run3(); 25 | 26 | Console.ReadKey(); 27 | } 28 | 29 | private static void PrintIds() 30 | { 31 | Console.WriteLine($"Current Thread Id: {Thread.CurrentThread.ManagedThreadId}"); 32 | Console.WriteLine($"Current Native Thread Id: {GetCurrentThreadId()}"); 33 | } 34 | 35 | private static void UsingFileWatcher1() 36 | { 37 | var fw = new FileWatcher(); 38 | fw.Run(); 39 | } 40 | 41 | private static void UsingBlockingPrimes() 42 | { 43 | Console.WriteLine("Start primes"); 44 | foreach (var n in new Primes(1000000)) { /* ... */ } 45 | Console.WriteLine("End primes"); // the wait is too long! 46 | } 47 | 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_01/chapter_12_01.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/KernelVsUserMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using BenchmarkDotNet.Attributes; 8 | 9 | namespace chapter_12_02 10 | { 11 | public class KernelVsUserMode 12 | { 13 | private ManualResetEvent kernelMode = new ManualResetEvent(false); 14 | private ManualResetEventSlim userMode = new ManualResetEventSlim(false); 15 | 16 | [Benchmark] 17 | public void KernelModeEvent() 18 | { 19 | kernelMode.Set(); 20 | kernelMode.Reset(); 21 | } 22 | 23 | [Benchmark] 24 | public void UserModeEvent() 25 | { 26 | userMode.Set(); 27 | userMode.Reset(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BenchmarkDotNet.Reports; 3 | using BenchmarkDotNet.Running; 4 | 5 | namespace chapter_12_02 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | Summary summary; 12 | 13 | //new SyncPingPong().PingPong(); 14 | //summary = BenchmarkRunner.Run(); 15 | //new SyncWaitMultiple().WaitMultiple(); 16 | //new SyncShared().Run(); 17 | 18 | Console.ReadKey(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/SyncPingPong.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace chapter_12_02 7 | { 8 | public class SyncPingPong 9 | { 10 | public void PingPong() 11 | { 12 | bool quit = false; 13 | var ping = new ManualResetEventSlim(false); 14 | var pong = new ManualResetEventSlim(false); 15 | ThreadPool.QueueUserWorkItem(_ => 16 | { 17 | Console.WriteLine($"Ping thread: {Thread.CurrentThread.ManagedThreadId}"); 18 | while (!quit) 19 | { 20 | pong.Wait(); 21 | pong.Reset(); 22 | Console.WriteLine("Ping"); 23 | Thread.Sleep(1000); 24 | ping.Set(); 25 | } 26 | }); 27 | ThreadPool.QueueUserWorkItem(_ => 28 | { 29 | Console.WriteLine($"Pong thread: {Thread.CurrentThread.ManagedThreadId}"); 30 | while (!quit) 31 | { 32 | ping.Wait(); 33 | ping.Reset(); 34 | Console.WriteLine("Pong"); 35 | Thread.Sleep(1000); 36 | pong.Set(); 37 | } 38 | }); 39 | 40 | pong.Set(); 41 | Console.ReadKey(); 42 | quit = true; 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/SyncShared.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace chapter_12_02 7 | { 8 | public class SyncShared 9 | { 10 | public void Run() 11 | { 12 | for (int i = 0; i < 15; i++) 13 | { 14 | SharedResource(); 15 | } 16 | } 17 | 18 | int _shared; 19 | int Shared 20 | { 21 | get => _shared; 22 | set { Thread.Sleep(1); _shared = value; } 23 | } 24 | ManualResetEvent evt = new ManualResetEvent(false); 25 | object sync = new object(); 26 | 27 | private void SharedResource() 28 | { 29 | Shared = 0; 30 | var loop = 100; 31 | var threads = new List(); 32 | for (int i = 0; i < loop; i++) 33 | { 34 | var t = new Thread(() => 35 | { 36 | evt.WaitOne(); 37 | 38 | /* 39 | There are two ways to protect the shared resource: 40 | - using the lock statement 41 | - using the Interlocked class 42 | Experiment with one of the two or without any to see the problem 43 | */ 44 | 45 | //lock (sync) 46 | { 47 | Shared++; 48 | } 49 | 50 | //Interlocked.Increment(ref _shared); 51 | }); 52 | t.Start(); 53 | threads.Add(t); 54 | } 55 | 56 | evt.Set(); // make all threads start together 57 | foreach (var t in threads) 58 | t.Join(); // wait for the thread to finish 59 | Console.WriteLine($"actual:{Shared}, expected:{loop}"); 60 | } 61 | 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/SyncWaitMultiple.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace chapter_12_02 7 | { 8 | public class SyncWaitMultiple 9 | { 10 | public void WaitMultiple() 11 | { 12 | var one = new ManualResetEvent(false); 13 | var two = new ManualResetEvent(false); 14 | 15 | ThreadPool.QueueUserWorkItem(_ => 16 | { 17 | Thread.Sleep(3000); 18 | one.Set(); 19 | }); 20 | ThreadPool.QueueUserWorkItem(_ => 21 | { 22 | Thread.Sleep(2000); 23 | two.Set(); 24 | }); 25 | 26 | // change the wait time above 2000 and 300 to see a different result 27 | int signaled = WaitHandle.WaitAny( 28 | new WaitHandle[] { one, two }, 500); 29 | switch (signaled) 30 | { 31 | case 0: 32 | Console.WriteLine("One was set"); 33 | break; 34 | case 1: 35 | Console.WriteLine("Two was set"); 36 | break; 37 | case WaitHandle.WaitTimeout: 38 | Console.WriteLine("Time expired"); 39 | break; 40 | } 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_02/chapter_12_02.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_01/FileOperations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter_12_03_01 9 | { 10 | public class FileOperations 11 | { 12 | public int ReadLength(string filename) 13 | { 14 | string content = File.ReadAllText(filename); 15 | return content.Length; 16 | } 17 | 18 | public Task ReadLengthAsync2(string filename) 19 | { 20 | Task length = File.ReadAllTextAsync(filename) 21 | .ContinueWith(t => t.Result.Length); 22 | return length; 23 | } 24 | 25 | public async Task ReadLengthAsync3(string filename) 26 | { 27 | string content = await File.ReadAllTextAsync(filename); 28 | return content.Length; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_01/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_01 5 | { 6 | class Program 7 | { 8 | static string filename = "DeBelloGallico_LiberI.txt"; 9 | 10 | static async Task Main(string[] args) 11 | { 12 | var f = new FileOperations(); 13 | var len1 = f.ReadLength(filename); 14 | var len2 = await f.ReadLengthAsync2(filename); 15 | var len3 = await f.ReadLengthAsync3(filename); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_01/chapter_12_03_01.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_02/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter_12_03_02 6 | { 7 | class Program 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | var p = new Program(); 12 | 13 | await p.WriteEmptyJsonObjectAsync("foo.json"); 14 | var s1 = await p.AddAsync1(1, 2); 15 | } 16 | 17 | public Task WriteEmptyJsonObjectAsync(string filename) 18 | { 19 | File.WriteAllText(filename, "{}"); 20 | return Task.CompletedTask; 21 | } 22 | 23 | public Task AddAsync1(int a, int b) 24 | { 25 | return Task.FromResult(a + b); 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_02/chapter_12_03_02.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_03/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_03 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var p = new Program(); 11 | var s2 = await p.AddAsync2(1, 2); 12 | } 13 | 14 | public ValueTask AddAsync2(int a, int b) 15 | { 16 | return new ValueTask(a + b); 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_03/chapter_12_03_03.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_05/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter_12_03_05 6 | { 7 | class Program 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | var filename = "DeBelloGallico_LiberI.txt"; 12 | var p = new Program(); 13 | var len = await p.ReadLengthAsync(filename); 14 | Console.WriteLine(len); 15 | } 16 | 17 | public Task ReadLengthAsync(string filename) 18 | { 19 | return Task.Run(() => 20 | { 21 | var content = File.ReadAllText(filename); 22 | return content.Length; 23 | }); 24 | } 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_05/chapter_12_03_05.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_06/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter_12_03_06 6 | { 7 | class Program 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | var t = new Task(() => Thread.Sleep(30000), 12 | TaskCreationOptions.LongRunning); 13 | 14 | // experiment with either of the following: 15 | t.Start(); 16 | //await t; 17 | 18 | Console.ReadKey(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_06/chapter_12_03_06.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_08/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_08 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var te = new TaskAndExceptions(); 11 | await te.Run(); 12 | Console.ReadKey(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_08/TaskAndExceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace chapter_12_03_08 7 | { 8 | public class TaskAndExceptions 9 | { 10 | public async Task Run() 11 | { 12 | int result; 13 | result = await HandleCrashBeforeAsync(); 14 | result = await HandleCrashAfterAsync(); 15 | result = await HandleCrashAfter2Async(); 16 | result = await CrashAfterAsync(); 17 | } 18 | 19 | public Task CrashBeforeAsync() 20 | { 21 | throw new Exception("Boom"); 22 | } 23 | 24 | public Task CrashAfterAsync() 25 | { 26 | //return Task.FromResult(0) 27 | // .ContinueWith(t => throw new Exception("Boom")); 28 | return Task.FromException(new Exception("Boom")); 29 | } 30 | 31 | public Task HandleCrashBeforeAsync() 32 | { 33 | Task resultTask; 34 | try 35 | { 36 | resultTask = CrashBeforeAsync(); 37 | } 38 | catch (Exception) { throw; } 39 | return resultTask; 40 | } 41 | 42 | public async Task HandleCrashAfterAsync() 43 | { 44 | Task resultTask = CrashAfterAsync(); 45 | int result; 46 | try 47 | { 48 | result = await resultTask; 49 | } 50 | catch (Exception) { throw; } 51 | return result; 52 | } 53 | 54 | public Task HandleCrashAfter2Async() 55 | { 56 | Task resultTask = CrashAfterAsync(); 57 | try 58 | { 59 | return resultTask.ContinueWith(t => 60 | { 61 | if (t.IsCompletedSuccessfully) return t.Result; 62 | if(t.Exception.InnerException is OverflowException) 63 | return -1; 64 | 65 | throw t.Exception.InnerException; 66 | }); 67 | } 68 | catch (Exception) { throw; } 69 | } 70 | 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_08/chapter_12_03_08.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_09/Cancelling0.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter_12_03_09 8 | { 9 | class CancellingATask 10 | { 11 | public async Task CancellingTask() 12 | { 13 | CancellationTokenSource cts2 = new 14 | CancellationTokenSource(TimeSpan.FromSeconds(2)); 15 | var tok2 = cts2.Token; 16 | 17 | try 18 | { 19 | await WorkForever1Async(tok2); 20 | await WorkForever2Async(tok2); 21 | await WorkForever3Async(tok2); 22 | Console.WriteLine("let's continue"); 23 | } 24 | catch (TaskCanceledException err) 25 | { 26 | Console.WriteLine(err.Message); 27 | } 28 | } 29 | 30 | public async Task WorkForever1Async( 31 | CancellationToken ct = default(CancellationToken)) 32 | { 33 | while (true) 34 | { 35 | await Task.Delay(5000, ct); 36 | } 37 | } 38 | 39 | public Task WorkForever2Async( 40 | CancellationToken ct = default(CancellationToken)) 41 | { 42 | while (true) 43 | { 44 | Thread.Sleep(5000); 45 | if (ct.IsCancellationRequested) return Task.FromCanceled(ct); 46 | } 47 | } 48 | 49 | public async Task WorkForever3Async( 50 | CancellationToken ct = default(CancellationToken)) 51 | { 52 | while (true) 53 | { 54 | await Task.Delay(5000); 55 | if (ct.IsCancellationRequested) return; 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_09/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_09 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var c = new CancellingATask(); 11 | await c.CancellingTask(); 12 | Console.ReadKey(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_09/chapter_12_03_09.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_10/MonitorProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace chapter_12_03_10 7 | { 8 | public class MonitorProgress 9 | { 10 | public async Task Load(IProgress progress = null) 11 | { 12 | var steps = 30; 13 | for (int i = 0; i < steps; i++) 14 | { 15 | await Task.Delay(300); 16 | progress?.Report((i + 1) * 100 / steps); 17 | } 18 | } 19 | 20 | } 21 | 22 | public class ConsoleProgress : IProgress 23 | { 24 | void IProgress.Report(int value) => 25 | Console.Write($"{value}% "); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_10/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_10 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var test = new MonitorProgress(); 11 | await test.Load(new ConsoleProgress()); 12 | Console.ReadKey(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_10/chapter_12_03_10.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_11/Parallelizing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace chapter_12_03_11 10 | { 11 | class Parallelizing 12 | { 13 | public async Task GetResourceAsync(string uri) 14 | { 15 | using var client = new HttpClient(); 16 | using var response = await client.GetAsync(uri); 17 | response.EnsureSuccessStatusCode(); 18 | return await response.Content.ReadAsByteArrayAsync(); 19 | } 20 | 21 | /// 22 | /// You can test the error by uncommenting one of the 23 | /// lines inside the Linq query 24 | /// 25 | /// 26 | public async Task NeedAll() 27 | { 28 | var uri = "https://picsum.photos/200"; 29 | Task[] tasks = Enumerable.Range(0, 10) 30 | .Select(_ => GetResourceAsync(uri)) 31 | //.Union(new Task[] { GetResourceAsync("http://bad") }) 32 | //.Union(new Task[] { Task.FromException(new Exception("fail simulation")) }) 33 | .ToArray(); 34 | 35 | Task allTask = Task.WhenAll(tasks); 36 | try 37 | { 38 | await allTask; 39 | } 40 | catch (Exception) 41 | { 42 | Console.WriteLine("One or more downloads failed"); 43 | } 44 | 45 | foreach (var completedTask in tasks) 46 | Console.WriteLine($"New image: {completedTask.Result.Length}"); 47 | } 48 | 49 | /// 50 | /// Experiment by commenting WhenAny and uncommenting WhenAll 51 | /// to verify the download differences 52 | /// 53 | /// 54 | public async Task NeedAny() 55 | { 56 | var sw = new Stopwatch(); 57 | sw.Start(); 58 | var uri = "https://picsum.photos/200"; 59 | Task[] tasks = Enumerable.Range(0, 10) 60 | .Select(_ => GetResourceAsync(uri)) 61 | .ToArray(); 62 | 63 | while (tasks.Length > 0) 64 | { 65 | await Task.WhenAny(tasks); 66 | //await Task.WhenAll(Task.Delay(100), Task.WhenAny(tasks)); 67 | var elapsed = sw.ElapsedMilliseconds; 68 | var completed = tasks.Where(t => t.IsCompleted).ToArray(); 69 | foreach (var completedTask in completed) 70 | Console.WriteLine($"{elapsed} New image: {completedTask.Result.Length}"); 71 | tasks = tasks.Where(t => !t.IsCompletedSuccessfully).ToArray(); 72 | } 73 | } 74 | 75 | /// 76 | /// Experiment by uncommenting the code inside the Linq query 77 | /// A download error will occur 78 | /// 79 | public void WaitAll() 80 | { 81 | var uri = "https://picsum.photos/200"; 82 | Task[] tasks = Enumerable.Range(0, 10) 83 | .Select(_ => GetResourceAsync(uri)) 84 | .Union(new Task[] { GetResourceAsync("http://bad") }) 85 | //.Union(new Task[] { Task.FromException(new Exception("fail simulation")) }) 86 | .ToArray(); 87 | 88 | Task.WaitAll(tasks); 89 | 90 | foreach (var completedTask in tasks) 91 | Console.WriteLine($"New image: {completedTask.Result.Length}"); 92 | } 93 | 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_11/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_11 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var w = new Parallelizing(); 11 | await w.NeedAll(); 12 | Console.WriteLine(); 13 | Console.WriteLine(); 14 | Console.WriteLine(); 15 | for (int i = 0; i < 4; i++) 16 | { 17 | await w.NeedAny(); 18 | Console.WriteLine(); 19 | } 20 | w.WaitAll(); 21 | 22 | Console.ReadKey(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_11/chapter_12_03_11.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_12/DeletionNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter_12_03_12 8 | { 9 | public class DeletionNotifier : IDisposable 10 | { 11 | private TaskCompletionSource _tcs; 12 | private FileSystemWatcher _watcher; 13 | 14 | public DeletionNotifier() 15 | { 16 | var path = Path.GetFullPath("."); 17 | Console.WriteLine($"Observing changes in path: {path}"); 18 | _watcher = new FileSystemWatcher(path, "*.txt"); 19 | _watcher.Deleted += (s, e) => 20 | { 21 | _watcher.EnableRaisingEvents = false; 22 | _tcs.SetResult(e); 23 | }; 24 | 25 | _watcher.Error += (s, e) => 26 | { 27 | _watcher.EnableRaisingEvents = false; 28 | _tcs.SetException(e.GetException()); 29 | }; 30 | } 31 | 32 | public Task WhenDeleted() 33 | { 34 | _tcs = new TaskCompletionSource(); 35 | _watcher.EnableRaisingEvents = true; 36 | return _tcs.Task; 37 | } 38 | 39 | public void Dispose() => _watcher.Dispose(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_12/DeletionNotifier2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter_12_03_12 9 | { 10 | public class DeletionNotifier2 : IDisposable 11 | { 12 | private TaskCompletionSource _tcs; 13 | private FileSystemWatcher _watcher; 14 | private ConcurrentQueue _queue; 15 | private Exception _error; 16 | 17 | public DeletionNotifier2() 18 | { 19 | var path = Path.GetFullPath("."); 20 | Console.WriteLine($"Observing changes in path: {path}"); 21 | _queue = new ConcurrentQueue(); 22 | _watcher = new FileSystemWatcher(path, "*.txt"); 23 | _watcher.Deleted += (s, e) => 24 | { 25 | _queue.Enqueue(e); 26 | _tcs.TrySetResult(e); 27 | }; 28 | _watcher.Error += (s, e) => 29 | { 30 | _watcher.EnableRaisingEvents = false; 31 | _error = e.GetException(); 32 | _tcs.TrySetException(_error); 33 | }; 34 | _watcher.EnableRaisingEvents = true; 35 | } 36 | 37 | public Task WhenDeleted() 38 | { 39 | if (_queue.TryDequeue(out FileSystemEventArgs fsea)) 40 | return Task.FromResult(fsea); 41 | 42 | if (_error != null) 43 | return Task.FromException(_error); 44 | 45 | _tcs = new TaskCompletionSource(); 46 | return _tcs.Task; 47 | } 48 | 49 | public void Dispose() => _watcher.Dispose(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_12/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter_12_03_12 6 | { 7 | class Program 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | await Test1(); 12 | await Test2(); 13 | await Test3(); 14 | Console.ReadKey(); 15 | } 16 | 17 | private static async Task Test1() 18 | { 19 | var dn = new DeletionNotifier(); 20 | var deleted = await dn.WhenDeleted(); 21 | Console.WriteLine($"Deleted: {deleted.Name}"); 22 | } 23 | 24 | private static async Task Test2() 25 | { 26 | var dn = new DeletionNotifier2(); 27 | var deleted = await dn.WhenDeleted(); 28 | Console.WriteLine($"Deleted: {deleted.Name}"); 29 | } 30 | 31 | private static async Task Test3() 32 | { 33 | var dn = new DeletionNotifier3(); 34 | while (true) 35 | { 36 | var deleted = await dn.WhenDeleted(); 37 | Console.WriteLine($"Deleted: {deleted.Name}"); 38 | Thread.Sleep(2500); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_12/chapter_12_03_12.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_13/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter_12_03_13 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var sc = new SyncContext(); 11 | await sc.AsyncTest1(); 12 | await sc.AsyncLoop(); 13 | Console.ReadKey(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_13/SyncContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter_12_03_13 9 | { 10 | class SyncContext 11 | { 12 | public async Task AsyncTest1() 13 | { 14 | Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}"); 15 | await Task.Delay(100); 16 | Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}"); 17 | await Task.Delay(100); 18 | Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}"); 19 | } 20 | 21 | /// 22 | /// Experiment by uncommenting the ConfigureAwait statement 23 | /// 24 | /// 25 | public async Task AsyncLoop() 26 | { 27 | Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}"); 28 | byte[] data; 29 | while((data = await GetNextAsync() 30 | //.ConfigureAwait(false) 31 | ).Length > 0) 32 | { 33 | Console.WriteLine($"Id: {Thread.CurrentThread.ManagedThreadId}"); 34 | // process data 35 | } 36 | } 37 | 38 | private int[] _simulateInt = new[] { 1000, 900, 1000, 1000, 0 }; 39 | private int _index = 0; 40 | public async Task GetNextAsync() 41 | { 42 | byte[] data; 43 | if (_index < _simulateInt.Length) 44 | { 45 | await Task.Delay(100); 46 | var result = _simulateInt[_index]; 47 | data = Enumerable.Range(0, result).Select(s => (byte)s).ToArray(); 48 | _index++; 49 | return data; 50 | } 51 | 52 | data = Array.Empty(); 53 | return data; 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_13/chapter_12_03_13.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace chapter_12_03_WPF 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/ImageConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Text; 6 | using System.Windows.Data; 7 | using System.Windows.Media.Imaging; 8 | 9 | namespace chapter_12_03_WPF 10 | { 11 | public class ImageConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (value is string resourceImage) 16 | { 17 | return GetImageFromPack(resourceImage); 18 | } 19 | 20 | if (value is byte[] blobImage) 21 | { 22 | var image = new BitmapImage(); 23 | image.BeginInit(); 24 | image.CacheOption = BitmapCacheOption.OnLoad; 25 | using (var ms = new MemoryStream()) 26 | { 27 | ms.Write(blobImage.AsSpan()); 28 | ms.Seek(0, SeekOrigin.Begin); 29 | image.StreamSource = ms; 30 | image.StreamSource.Seek(0, SeekOrigin.Begin); 31 | image.EndInit(); 32 | } 33 | 34 | return image; 35 | } 36 | 37 | return null; 38 | } 39 | 40 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 41 | { 42 | throw new NotImplementedException(); 43 | } 44 | 45 | public static BitmapImage GetImageFromPack(string resourceName) 46 | { 47 | Uri uri = new Uri("pack://application:,,,/" + resourceName, UriKind.RelativeOrAbsolute); 48 | return new BitmapImage(uri); 49 | } 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/ImageInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace chapter_12_03_WPF 6 | { 7 | public class ImageInfo 8 | { 9 | public byte[] Blob { get; set; } 10 | public string Title { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/chapter_12/chapter_12_03_WPF/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |