├── .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 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/chapter_12/chapter_12_03_WPF/UserInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.CompilerServices;
4 | using System.Text;
5 | using System.Threading;
6 |
7 | namespace chapter_12_03_WPF
8 | {
9 | public class UserInterface : INotifyCompletion
10 | {
11 | private Exception _error;
12 | private Action _continuation;
13 | private SynchronizationContext _uiContext;
14 | public UserInterface()
15 | {
16 | _uiContext = SynchronizationContext.Current;
17 | }
18 |
19 | public UserInterface GetAwaiter() => this;
20 | public UserInterface Task => this;
21 | public bool IsCompleted => _uiContext == SynchronizationContext.Current;
22 |
23 | void INotifyCompletion.OnCompleted(Action continuation)
24 | {
25 | _uiContext.Post(s => ((Action)s)(), continuation);
26 | //_uiContext.Post(_ => continuation(), null);
27 | }
28 |
29 | public void GetResult()
30 | {
31 | }
32 |
33 | public bool TrySetException(Exception exception)
34 | {
35 | if (IsCompleted) return false;
36 | _error = exception;
37 | _continuation?.Invoke();
38 | return true;
39 | }
40 |
41 | public void Reset()
42 | {
43 | _error = null;
44 | _continuation = null;
45 | }
46 |
47 | public UserInterface FromException(Exception exception)
48 | {
49 | Reset();
50 | TrySetException(exception);
51 | return this;
52 | }
53 |
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/chapter_12/chapter_12_03_WPF/chapter_12_03_WPF.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | netcoreapp3.1
6 | true
7 |
8 |
9 |
10 |
11 | PreserveNewest
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_01/chapter_13_01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_02/chapter_13_02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_03/chapter_13_03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_04/Program.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Converters;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 |
7 | namespace chapter_13_04
8 | {
9 | public enum EmployeeStatus
10 | {
11 | Active,
12 | Inactive
13 | }
14 |
15 | public class Employee
16 | {
17 | public int EmployeeId { get; set; }
18 |
19 | public string FirstName { get; set; }
20 |
21 | public string LastName { get; set; }
22 |
23 | public DateTime? HireDate { get; set; }
24 |
25 | public List Telephones { get; set; }
26 |
27 | public bool IsOnLeave { get; set; }
28 |
29 | [JsonConverter(typeof(StringEnumConverter))]
30 | public EmployeeStatus Status { get; set; }
31 |
32 | [JsonIgnore]
33 | public DateTime LastModified { get; set; }
34 |
35 | public override string ToString() => $"[{EmployeeId}] {LastName}, {FirstName}";
36 | }
37 |
38 | class Program
39 | {
40 | static void Main(string[] args)
41 | {
42 | var employee = new Employee
43 | {
44 | EmployeeId = 42,
45 | FirstName = "John",
46 | LastName = "Doe"
47 | };
48 |
49 | {
50 | var text = JsonConvert.SerializeObject(employee);
51 | Console.WriteLine(text);
52 | }
53 |
54 | {
55 | var text = JsonConvert.SerializeObject(employee, Formatting.Indented);
56 | Console.WriteLine(text);
57 | }
58 |
59 | {
60 | var text = JsonConvert.SerializeObject(
61 | employee,
62 | Formatting.Indented,
63 | new JsonSerializerSettings()
64 | {
65 | NullValueHandling = NullValueHandling.Ignore,
66 | });
67 | Console.WriteLine(text);
68 | }
69 |
70 | {
71 | var text = JsonConvert.SerializeObject(
72 | employee,
73 | Formatting.Indented,
74 | new JsonSerializerSettings()
75 | {
76 | NullValueHandling = NullValueHandling.Ignore,
77 | DefaultValueHandling = DefaultValueHandling.Ignore
78 | });
79 | Console.WriteLine(text);
80 | }
81 |
82 | {
83 | var path = Path.Combine(Path.GetTempPath() + "employee.json");
84 | var serializer = new JsonSerializer()
85 | {
86 | Formatting = Formatting.Indented,
87 | NullValueHandling = NullValueHandling.Ignore,
88 | DefaultValueHandling = DefaultValueHandling.Ignore
89 | };
90 |
91 | using (var sw = File.CreateText(path))
92 | using (var jw = new JsonTextWriter(sw))
93 | {
94 | serializer.Serialize(jw, employee);
95 | }
96 |
97 | Console.WriteLine(File.ReadAllText(path));
98 |
99 | using (var sr = File.OpenText(path))
100 | using (var jr = new JsonTextReader(sr))
101 | {
102 | var result = serializer.Deserialize(jr);
103 |
104 | Console.WriteLine(result);
105 | }
106 |
107 | File.Delete(path);
108 | }
109 |
110 | var json =
111 | @"{
112 | ""EmployeeId"": 42,
113 | ""FirstName"": ""John"",
114 | ""LastName"": ""Doe""
115 | }";
116 | Console.WriteLine(json);
117 |
118 | {
119 | var result = JsonConvert.DeserializeObject(json);
120 |
121 | Console.WriteLine(result);
122 | }
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_04/chapter_13_04.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/chapter_13/chapter_13_05/chapter_13_05.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_01/ErrorsVsExceptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace chapter_14_01
6 | {
7 | [TestClass]
8 | public class ErrorsVsExceptions
9 | {
10 | [TestMethod]
11 | public void TestMethod1()
12 | {
13 | var api = new SomeApi();
14 | if (api.Begin() == 0)
15 | {
16 | if (api.DoWork() == 0)
17 | {
18 | api.End();
19 | }
20 | }
21 | }
22 |
23 | [TestMethod]
24 | public void TestMethod2()
25 | {
26 | var a = 1;
27 | var b = 0;
28 | // division by zero with integers
29 | Assert.ThrowsException(() => a / b);
30 | }
31 |
32 | [TestMethod]
33 | public void TestMethod3()
34 | {
35 | var a = 1.0m;
36 | var b = 0.0m;
37 | // division by zero with decimals
38 | Assert.ThrowsException(() => a / b);
39 | }
40 |
41 | [TestMethod]
42 | public void TestMethod4()
43 | {
44 | var a = 1.0;
45 | var b = 0.0;
46 | // division by zero with floating points
47 | Assert.AreEqual(double.PositiveInfinity, a / b);
48 | }
49 |
50 | [TestMethod]
51 | public void TestMethod5()
52 | {
53 | int a = int.MaxValue;
54 | // unless it is wrapped with "checked", it won't throw
55 | // checking for overflow every math operation would be a perf hit
56 | Assert.ThrowsException(() => checked(a++));
57 | }
58 | }
59 |
60 | public class SomeApi
61 | {
62 | public int Begin() => (int)ErrorCodes.Success;
63 | public int DoWork() => (int)ErrorCodes.Success;
64 | public int End() => (int)ErrorCodes.GeneralFailure;
65 | }
66 |
67 |
68 | public enum ErrorCodes : int
69 | {
70 | Success = 0,
71 | InvalidParameter = 1,
72 | NotFound = 2,
73 | GeneralFailure = 10,
74 | //...
75 | }
76 |
77 | public class Calculator
78 | {
79 | public double Div(double a, double b)
80 | {
81 | return a / b;
82 | }
83 |
84 | public int Div(double a, double b, out double result)
85 | {
86 | if (b == 0)
87 | {
88 | result = 0;
89 | return (int)ErrorCodes.InvalidParameter;
90 | }
91 |
92 | result = a / b;
93 | return (int)ErrorCodes.Success;
94 | }
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_01/chapter_14_01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_01/Catching.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 |
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace chapter_14_02_01
8 | {
9 | [TestClass]
10 | public class Catching
11 | {
12 | [TestMethod]
13 | public void TestMethod1()
14 | {
15 | ReadTextFile2(false, "EmptyFile.txt");
16 | ReadTextFile3(false, "NotExistentFile.txt");
17 |
18 | Assert.IsNull(ReadTextFile(true, "//"));
19 | Assert.ThrowsException(() => ReadTextFile(false, "//"));
20 |
21 | Assert.AreEqual(0, ReadTextFile2(true, "//"));
22 | Assert.AreEqual(0, ReadTextFile2(false, "//"));
23 | }
24 |
25 | public string ReadTextFile(bool validateExistence, string filename)
26 | {
27 | if (validateExistence && !File.Exists(filename)) return null;
28 | var content = File.ReadAllText(filename);
29 | return content;
30 | }
31 |
32 | public int ReadTextFile2(bool validateExistence, string filename)
33 | {
34 | try
35 | {
36 | if (validateExistence && !File.Exists(filename)) return 0;
37 | var content = File.ReadAllText(filename);
38 | return content.Length;
39 | }
40 | catch (Exception)
41 | {
42 | return 0;
43 | }
44 | }
45 |
46 | public int ReadTextFile3(bool validateExistence, string filename)
47 | {
48 | try
49 | {
50 | if (validateExistence && !File.Exists(filename)) return 0;
51 | var content = File.ReadAllText(filename);
52 | return content.Length;
53 | }
54 | catch (ArgumentNullException) { /* ... */ }
55 | catch (IOException) { /* ... */ }
56 | catch (UnauthorizedAccessException) { /* ... */ }
57 | catch (Exception) { /* ... */ }
58 |
59 | return 0;
60 | }
61 |
62 | public void CopyReversedTextFile(string source, string target)
63 | {
64 | try
65 | {
66 | var content = ReadTextFile(source);
67 | content = content.Replace("\r\n", "\r");
68 | WriteTextFile(target, content);
69 | }
70 | catch (IOException) { /*...*/ }
71 | }
72 |
73 | public string ReadTextFile(string filename)
74 | {
75 | try
76 | {
77 | var content = File.ReadAllText(filename);
78 | return content;
79 | }
80 | catch (ArgumentNullException) { /* ... */ }
81 | return null;
82 | }
83 |
84 | public void WriteTextFile(string filename, string content)
85 | {
86 | try
87 | {
88 | File.WriteAllText(filename, content);
89 | }
90 | catch (ArgumentNullException) { /* ... */ }
91 | }
92 |
93 | }
94 |
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_01/chapter_14_02_01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_02/EmptyFile.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Learn-C-Sharp-Programming/6c895f9c4478946ebac56fe349849a3dba26a64e/src/chapter_14/chapter_14_02_02/EmptyFile.txt
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_02/ExceptionObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 |
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace chapter_14_02_02
8 | {
9 | [TestClass]
10 | public class ExceptionObject
11 | {
12 | [TestMethod]
13 | public void TestMethod1()
14 | {
15 | var sizes = GetFileLengths("DeBelloGallico_LiberI.txt", "EmptyFile.txt");
16 | Assert.AreEqual(2, sizes.Length);
17 | Assert.AreEqual(0, sizes[1]);
18 | }
19 |
20 | int[] GetFileLengths(params string[] filenames)
21 | {
22 | try
23 | {
24 | var sizes = new int[filenames.Length];
25 | int i = 0;
26 | foreach (var filename in filenames)
27 | {
28 | var content = File.ReadAllText(filename);
29 | sizes[i++] = content.Length; // may differ from file size
30 | }
31 | return sizes;
32 | }
33 | catch (FileNotFoundException err)
34 | {
35 | Debug.WriteLine($"Cannot find {err.FileName}");
36 | return null;
37 | }
38 | }
39 |
40 |
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_02/chapter_14_02_02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | PreserveNewest
19 |
20 |
21 | PreserveNewest
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_03/ConditionalCatch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 |
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace chapter_14_02_03
8 | {
9 | [TestClass]
10 | public class ConditionalCatch
11 | {
12 | [TestMethod]
13 | public void TestMethod1()
14 | {
15 | CopyFrom(null);
16 | Assert.ThrowsException(() => CopyFrom2(null));
17 | CopyFrom3("EmptyFile.txt");
18 | }
19 |
20 | [TestMethod]
21 | public void TestMethod2()
22 | {
23 | try
24 | {
25 | File.Copy(null, null);
26 | }
27 | catch (FileNotFoundException err)
28 | {
29 | Debug.WriteLine($"Can't find: {err.FileName}");
30 | Assert.Fail();
31 | return;
32 | }
33 | catch (ArgumentNullException)
34 | {
35 | return; // ok
36 | }
37 |
38 | Assert.Fail();
39 | }
40 |
41 | private void CopyFrom(string source)
42 | {
43 | try
44 | {
45 | var target = CreateFilename(source);
46 | File.Copy(source, target);
47 | }
48 | catch (ArgumentException err)
49 | {
50 | Debug.WriteLine($"The parameter {err.ParamName} is invalid");
51 | return;
52 | }
53 | }
54 |
55 | private void CopyFrom2(string source)
56 | {
57 | try
58 | {
59 | var target = CreateFilename(source);
60 | File.Copy(source, target);
61 | }
62 | catch (ArgumentException err) when (err.ParamName == "destFileName")
63 | {
64 | Debug.WriteLine($"The parameter {err.ParamName} is invalid");
65 | return;
66 | }
67 | }
68 |
69 | private void CopyFrom3(string source)
70 | {
71 | var target = CreateFilename(source);
72 | try
73 | {
74 | File.Copy(source, target);
75 | }
76 | catch (ArgumentException err) when (target is null)
77 | {
78 | Debug.WriteLine($"The parameter {err.ParamName} is invalid");
79 | return;
80 | }
81 | }
82 |
83 | ///
84 | /// The generated filename is wrong on purpose
85 | ///
86 | string CreateFilename(string name) => null;//$"//{name}";
87 |
88 |
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_03/chapter_14_02_03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_04/Throwing.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_14_02_04
7 | {
8 | [TestClass]
9 | public class Throwing
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | Assert.ThrowsException(() => ReadLog0(null));
15 | Assert.ThrowsException(() => ReadLog1(null));
16 | Assert.ThrowsException(() => ReadLog2(null));
17 | }
18 |
19 | private string ReadLog0(string logName)
20 | {
21 | return File.ReadAllText(logName);
22 | }
23 |
24 | private string ReadLog1(string logName)
25 | {
26 | var filename = "App-" + (logName.EndsWith(".log") ? logName : logName + ".log");
27 | return File.ReadAllText(filename);
28 | }
29 |
30 | private string ReadLog2(string logName)
31 | {
32 | if (logName == null) throw new ArgumentNullException(nameof(logName));
33 | var filename = "App-" + (logName.EndsWith(".log") ? logName : logName + ".log");
34 | return File.ReadAllText(filename);
35 | }
36 |
37 |
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_04/chapter_14_02_04.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_04_benchmark/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using BenchmarkDotNet.Reports;
4 | using BenchmarkDotNet.Running;
5 |
6 |
7 | namespace chapter_14_02_04_benchmark
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | Summary summary;
14 | summary = BenchmarkRunner.Run();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_04_benchmark/ThrowingPerf.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.CompilerServices;
4 | using System.Text;
5 |
6 | using BenchmarkDotNet.Attributes;
7 |
8 |
9 | namespace chapter_14_02_04_benchmark
10 | {
11 | [MemoryDiagnoser]
12 | public class ThrowingPerf
13 | {
14 | public int Loop { get; } = 1000;
15 |
16 | [Benchmark]
17 | public void LoopNop()
18 | {
19 | for (var i = 0; i < Loop; i++)
20 | {
21 | try
22 | {
23 | Nop(i);
24 | }
25 | catch (Exception) { }
26 | }
27 | }
28 |
29 | [Benchmark]
30 | public void LoopEx()
31 | {
32 | for (var i = 0; i < Loop; i++)
33 | {
34 | try
35 | {
36 | Crash(i);
37 | }
38 | catch (Exception) { }
39 | }
40 | }
41 |
42 |
43 | [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
44 | private void Nop(int i)
45 | {
46 | }
47 |
48 | [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
49 | private void Crash(int i)
50 | {
51 | throw new InvalidOperationException();
52 | }
53 |
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_04_benchmark/chapter_14_02_04_benchmark.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_05/CustomExceptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Runtime.ExceptionServices;
5 |
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace chapter_14_02_05
9 | {
10 | [TestClass]
11 | public class CustomExceptions
12 | {
13 | [TestMethod]
14 | public void TestMethod1()
15 | {
16 | Assert.ThrowsException(() => GetCustomerNames("John"));
17 | }
18 |
19 | public IList GetCustomerNames(string queryKeyword)
20 | {
21 | var repository = new Repository();
22 | try
23 | {
24 | return repository.GetCustomerNames(queryKeyword);
25 | }
26 | catch (Exception err)
27 | {
28 | throw new DataLayerException($"Error on repository {repository.RepositoryName}",
29 | err, queryKeyword);
30 | }
31 | }
32 |
33 | public class Repository
34 | {
35 | public string RepositoryName { get; } = "DiskRepository";
36 | public IList GetCustomerNames(string queryKeyword)
37 | {
38 | throw new IOException("Something got wrong");
39 | }
40 | }
41 |
42 | public class DataLayerException : Exception
43 | {
44 | public DataLayerException(string queryKeyword = null)
45 | : base()
46 | {
47 | this.QueryKeyword = queryKeyword;
48 | }
49 |
50 | public DataLayerException(string message, string queryKeyword = null)
51 | : base(message)
52 | {
53 | this.QueryKeyword = queryKeyword;
54 | }
55 |
56 | public DataLayerException(string message, Exception innerException, string queryKeyword = null)
57 | : base(message, innerException)
58 | {
59 | this.QueryKeyword = queryKeyword;
60 | }
61 |
62 | public string QueryKeyword { get; private set; }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_05/chapter_14_02_05.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_06/Rethrowing1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_14_02_06
7 | {
8 | [TestClass]
9 | public class Rethrowing1
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | Assert.ThrowsException(() => ReadAllText("abc.txt"));
15 | }
16 |
17 | public string ReadAllText(string filename)
18 | {
19 | try
20 | {
21 | return File.ReadAllText(filename);
22 | }
23 | catch (Exception err)
24 | {
25 | Log(err.ToString());
26 | //throw;
27 | throw err;
28 | }
29 | }
30 |
31 | private void Log(string content) { }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_06/Rethrowing2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.ExceptionServices;
4 |
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace chapter_14_02_06
8 | {
9 | [TestClass]
10 | public class Rethrowing2
11 | {
12 | [TestMethod]
13 | public void TestMethod1()
14 | {
15 | Assert.ThrowsException(() => Foo());
16 | }
17 |
18 |
19 | public void Foo()
20 | {
21 | ExceptionDispatchInfo exceptionDispatchInfo = null;
22 | try
23 | {
24 | ExecuteFunctionThatThrows();
25 | }
26 | catch (Exception ex)
27 | {
28 | exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
29 | }
30 |
31 | // do something you cannot do in the catch block
32 |
33 | // rethrow
34 | if (exceptionDispatchInfo != null)
35 | exceptionDispatchInfo.Throw();
36 | }
37 |
38 | private void ExecuteFunctionThatThrows()
39 | {
40 | throw new NotImplementedException();
41 | }
42 |
43 | private ExceptionDispatchInfo CaptureException()
44 | {
45 | try
46 | {
47 | string x = null;
48 | x.Trim();
49 | return null;
50 | }
51 | catch (Exception err)
52 | {
53 | return ExceptionDispatchInfo.Capture(err);
54 | }
55 | }
56 |
57 |
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_06/chapter_14_02_06.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_07/Finally.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_14_02_07
7 | {
8 | [TestClass]
9 | public class Finally
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | // this is not really a test but
15 | // take a look at the test output
16 | M1();
17 | // == with catch in M3 ==
18 | //catch in M3
19 | //finally in M3
20 | //finally in M2
21 | //finally in M1
22 |
23 | // == without catch in M3 ==
24 | //finally in M3
25 | //catch in M2
26 | //finally in M2
27 | //finally in M1
28 | }
29 |
30 | private void M1()
31 | {
32 | try { M2(); }
33 | catch (Exception) { Debug.WriteLine("catch in M1"); }
34 | finally { Debug.WriteLine("finally in M1"); }
35 | }
36 |
37 | private void M2()
38 | {
39 | try { M3(); }
40 | catch (Exception) { Debug.WriteLine("catch in M2"); }
41 | finally { Debug.WriteLine("finally in M2"); }
42 | }
43 |
44 | private void M3()
45 | {
46 | try { Crash(); }
47 | finally { Debug.WriteLine("finally in M3"); }
48 | }
49 |
50 | private void Crash() => throw new Exception("Boom");
51 |
52 |
53 |
54 | private class Resource : IDisposable
55 | {
56 | public void Dispose()
57 | {
58 | }
59 | }
60 |
61 | void FinallyBlock()
62 | {
63 | Resource res = new Resource();
64 | try
65 | {
66 | Console.WriteLine();
67 | }
68 | finally
69 | {
70 | res?.Dispose();
71 | }
72 | }
73 |
74 | void UsingStatement()
75 | {
76 | using (var res = new Resource())
77 | {
78 | Console.WriteLine();
79 | }
80 | }
81 |
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_02_07/chapter_14_02_07.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_03/ExceptionEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace chapter_14_03
6 | {
7 | public class ExceptionEvent
8 | {
9 | public void TestMethod1()
10 | {
11 | A();
12 | }
13 |
14 | private void A() => B();
15 |
16 | private void B()
17 | {
18 | try
19 | {
20 | C();
21 | }
22 | catch (Exception err)
23 | {
24 | throw new Exception("B Exception");
25 | }
26 | }
27 |
28 | private void C()
29 | {
30 | try
31 | {
32 | D();
33 | }
34 | catch (Exception err)
35 | {
36 | throw new Exception("C Exception", err);
37 | }
38 | }
39 |
40 | private void D()
41 | {
42 | try
43 | {
44 | Crash();
45 | }
46 | catch (Exception)
47 | {
48 | throw;
49 | }
50 | }
51 |
52 | private void Crash() => throw new Exception("Crashing");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_03/FirstSecondChance.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace chapter_14_03
6 | {
7 | public class FirstSecondChance
8 | {
9 | public void TestMethod1()
10 | {
11 | Crash1();
12 | }
13 |
14 | private void Crash1() => throw new Exception("This will make the app crash");
15 |
16 |
17 | public void TestMethod2() => Crash2(null);
18 |
19 | private void Crash2(string str) => Console.WriteLine(str.Length);
20 |
21 | public void TestMethod3()
22 | {
23 | try
24 | {
25 | // Open the Exception Settings (Ctrl-Alt-E)
26 | // Experiment by checking/unchecking "System.Exception" and re-run this code
27 | Crash1();
28 | }
29 | catch (Exception)
30 | {
31 | }
32 | }
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_03/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace chapter_14_03
4 | {
5 | class Program
6 | {
7 | static void Main(string[] args)
8 | {
9 | AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
10 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
11 |
12 | var p = new FirstSecondChance();
13 | //p.TestMethod1();
14 | //p.TestMethod2();
15 | //p.TestMethod3();
16 |
17 | var ee = new ExceptionEvent();
18 | ee.TestMethod1();
19 | }
20 |
21 | private static void CurrentDomain_FirstChanceException(object sender,
22 | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
23 | {
24 | Console.WriteLine($"First-Chance. {e.Exception.Message}");
25 | Dump(e.Exception);
26 | }
27 |
28 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
29 | {
30 | var ex = (Exception)e.ExceptionObject;
31 | Console.WriteLine($"Unhandled Exception. IsTerminating: {e.IsTerminating} - {ex.Message}");
32 | Dump(ex);
33 | }
34 |
35 | private static void Dump1(Exception err)
36 | {
37 | var current = err;
38 | while (current != null)
39 | {
40 | Console.WriteLine(current.InnerException?.Message);
41 | current = current.InnerException;
42 | }
43 | }
44 |
45 | private static void Dump2(Exception err)
46 | {
47 | Console.WriteLine(err);
48 | }
49 |
50 | private static void Dump3(Exception err)
51 | {
52 | Console.WriteLine(err.TargetSite.Name);
53 | }
54 |
55 | private static void Dump(Exception err)
56 | {
57 | var be = err.GetBaseException();
58 | Console.WriteLine($"err:{err.TargetSite.Name} - base:{be.TargetSite.Name}");
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/chapter_14/chapter_14_03/chapter_14_03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_01/Nullable1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_01.Nullable1
5 | {
6 | [TestClass]
7 | public class Nullable1
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | Assert.ThrowsException(() => new SomeClass().NameLength);
13 | Assert.IsTrue(new SomeClass("Raf").NameLength >= 0);
14 | }
15 |
16 |
17 | public class SomeClass
18 | {
19 | private string _name;
20 |
21 | public SomeClass() { }
22 | public SomeClass(string name) { _name = name; }
23 |
24 | public int NameLength
25 | {
26 | get { return _name.Length; }
27 | }
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_01/Nullable2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_01.Nullable2
5 | {
6 | [TestClass]
7 | public class Nullable2
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | var someObject1 = new SomeClass();
13 | Assert.IsTrue(someObject1.NameLength1 == 0);
14 | Assert.IsTrue(someObject1.NameLength2 == 0);
15 |
16 | var someObject2 = new SomeClass("Raf");
17 | Assert.IsTrue(someObject2.NameLength1 == 3);
18 | Assert.IsTrue(someObject2.NameLength2 == 3);
19 | }
20 |
21 |
22 | #nullable enable
23 | public class SomeClass
24 | {
25 | private string? _name;
26 |
27 | public SomeClass() { }
28 | public SomeClass(string name) { _name = name; }
29 |
30 | public int NameLength1
31 | {
32 | get { return _name?.Length ?? 0; }
33 | }
34 |
35 | public int NameLength2
36 | {
37 | get
38 | {
39 | if (_name == null) return 0; else return _name.Length;
40 | }
41 | }
42 | public int NameLength3
43 | {
44 | get { return _name!.Length; }
45 | }
46 |
47 | }
48 | #nullable restore
49 | }
50 | }
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_01/Nullable3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_01.Nullable3
5 | {
6 | [TestClass]
7 | public class Nullable3
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | var someObject1 = new OtherClass();
13 | Assert.IsTrue(someObject1.GetItemLength(0) == string.Empty);
14 | }
15 |
16 |
17 | #nullable enable
18 | public class OtherClass
19 | {
20 | private string?[]? _names;
21 |
22 | public OtherClass() { }
23 |
24 | public int Count => _names?.Length ?? 0;
25 |
26 | public string GetItemLength(int index)
27 | {
28 | if (_names == null) return string.Empty;
29 | var name = _names[index];
30 | if (name == null) return string.Empty;
31 | return name;
32 | }
33 |
34 | }
35 | #nullable restore
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_01/chapter_15_01.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/InterfaceMembers1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_02
5 | {
6 | [TestClass]
7 | public class InterfaceMembers1
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | ICalc calc = new Calc();
13 | Assert.AreEqual(4, calc.Add(1, 3));
14 | Assert.AreEqual(3, calc.Mul(1, 3));
15 | }
16 |
17 | public class Calc : ICalc { }
18 |
19 | public interface ICalc
20 | {
21 | int Add(int x, int y) => x + y;
22 | int Mul(int x, int y) => x * y;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/InterfaceMembers2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_02
5 | {
6 | [TestClass]
7 | public class InterfaceMembers2
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | var p = new Person("John", "Doe");
13 | //p.Greet(); // Wrong, Greet() is not available in Person
14 | }
15 |
16 | [TestMethod]
17 | public void TestMethod2()
18 | {
19 | IWelcome p = new Person("John", "Doe");
20 | //p.Greet(); // Wrong, Greet() is not available in Person
21 | Assert.AreEqual("Welcome John", p.Greet());
22 | }
23 |
24 | public interface IWelcome
25 | {
26 | string FirstName { get; }
27 | string LastName { get; }
28 | string Greet() => $"Welcome {FirstName}";
29 | }
30 |
31 |
32 | public class Person : IWelcome
33 | {
34 | public Person(string firstName, string lastName)
35 | {
36 | this.FirstName = firstName;
37 | this.LastName = lastName;
38 | }
39 |
40 | public string FirstName { get; }
41 | public string LastName { get; }
42 | }
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/InterfaceMembers3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_02
5 | {
6 | [TestClass]
7 | public class InterfaceMembers3
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | IDog archie = new Labrador("Archie");
13 | //Assert.AreEqual("barks", archie.Noise); // V1
14 | Assert.AreEqual("woofs", archie.Noise); // V2
15 | }
16 |
17 | public interface IDog
18 | {
19 | string Name { get; }
20 | string Noise => "barks";
21 | }
22 |
23 | public interface ILabrador : IDog
24 | {
25 | int RetrieverAbility { get; }
26 | string IDog.Noise => "woofs"; // V2
27 | }
28 |
29 | public class Labrador : ILabrador
30 | {
31 | public Labrador(string name)
32 | {
33 | this.Name = name;
34 | }
35 |
36 | public string Name { get; }
37 | public int RetrieverAbility { get; set; }
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/InterfaceMembers4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_02
5 | {
6 | [TestClass]
7 | public class InterfaceMembers4
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | IDog archie = new Labrador("Archie");
13 | //Assert.AreEqual("barks", archie.Noise); // V1
14 | Assert.AreEqual("woofs", archie.Noise); // V2
15 | }
16 |
17 | public interface IDog
18 | {
19 | string Name { get; }
20 | string Noise => "barks";
21 | }
22 |
23 | public interface ILabrador : IDog
24 | {
25 | int RetrieverAbility { get; }
26 | string IDog.Noise => "woofs"; // V2
27 | }
28 |
29 | public interface IYellowLabrador : ILabrador
30 | {
31 | abstract string IDog.Noise { get; }
32 | }
33 |
34 | public class YellowLabrador : IYellowLabrador
35 | {
36 | public YellowLabrador(string name)
37 | {
38 | this.Name = name;
39 | }
40 |
41 | public string Name { get; }
42 | public int RetrieverAbility { get; set; }
43 | public string Noise { get; set; }
44 | }
45 |
46 | public class Labrador : ILabrador
47 | {
48 | public Labrador(string name)
49 | {
50 | this.Name = name;
51 | }
52 |
53 | public string Name { get; }
54 | public int RetrieverAbility { get; set; }
55 | }
56 |
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/InterfaceMembers5.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using NickBuhro.Translit;
4 |
5 | namespace chapter_15_02
6 | {
7 | [TestClass]
8 | public class InterfaceMembers5
9 | {
10 | [TestMethod]
11 | public void TestMethod1()
12 | {
13 | var t = new CompositeTransliterator();
14 | var input = "Matryoshka";
15 |
16 | var russian = t.TransliterateCyrillic(input);
17 | Assert.AreEqual("Матрёшка", russian);
18 | var latin = t.TransliterateCyrillic(russian);
19 | Assert.AreEqual(input, latin);
20 | }
21 |
22 | [TestMethod]
23 | public void TestMethod2()
24 | {
25 | var t = new CompositeTransliterator();
26 | var input = "你好";
27 | Assert.ThrowsException(
28 | () => t.TransliterateCyrillic(input));
29 | }
30 |
31 | public interface ICyrillicToLatin
32 | {
33 | public string Convert(string input)
34 | {
35 | return Transliteration.CyrillicToLatin(input, Language.Russian);
36 | }
37 | }
38 |
39 | public interface ILatinToCyrillic
40 | {
41 | public string Convert(string input)
42 | {
43 | return Transliteration.LatinToCyrillic(input, Language.Russian);
44 | }
45 | }
46 |
47 | public class CompositeTransliterator : ICyrillicToLatin, ILatinToCyrillic
48 | {
49 | public string TransliterateCyrillic(string input)
50 | {
51 | string result;
52 | return this switch
53 | {
54 | ICyrillicToLatin c when (result = c.Convert(input)) != input => result,
55 |
56 | ILatinToCyrillic l when (result = l.Convert(input)) != input => result,
57 |
58 | _ => throw new NotImplementedException("Can't find a suitable language"),
59 | };
60 | }
61 | }
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_02/chapter_15_02.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_03/RangesIndices2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_15_03.RangesIndices2
7 | {
8 | [TestClass]
9 | public class RangesIndices2
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | var countries = new MyList(new[] { "Italy", "Romania", "Switzerland", "Germany", "France", "England" });
15 | var expected = new[] { "Romania", "Switzerland", "Germany", "France" };
16 |
17 | MyList sliced = countries[1..^1];
18 | Assert.IsTrue(expected.SequenceEqual(sliced));
19 | }
20 |
21 | }
22 |
23 | public class MyList : List
24 | {
25 | public MyList() { }
26 | public MyList(IEnumerable items) : base(items) { }
27 |
28 | public MyList this[Range range]
29 | {
30 | get
31 | {
32 | (var from, var count) = range.GetOffsetAndLength(this.Count);
33 | return new MyList(this.GetRange(from, count));
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_03/RangesIndices3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_15_03.RangesIndices3
7 | {
8 | [TestClass]
9 | public class RangesIndices3
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | var countries = new MyList(new[] { "Italy", "Romania", "Switzerland", "Germany", "France", "England" });
15 | var expected = new[] { "Romania", "Switzerland", "Germany", "France" };
16 |
17 | MyList sliced = countries[1..^1];
18 | Assert.IsTrue(expected.SequenceEqual(sliced));
19 | }
20 |
21 | }
22 |
23 | public class MyList : List
24 | {
25 | public MyList() { }
26 | public MyList(IEnumerable items) : base(items) { }
27 |
28 | public MyList Slice(int offset, int count)
29 | {
30 | return new MyList(this.GetRange(offset, count));
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_03/RangesIndices4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace chapter_15_03.RangesIndices4
7 | {
8 | [TestClass]
9 | public class RangesIndices4
10 | {
11 | [TestMethod]
12 | public void TestMethod1()
13 | {
14 | var countries = new[] { "Italy", "Romania", "Switzerland", "Germany", "France", "England" }
15 | .ToList();
16 | var expected = new[] { "Romania", "Switzerland", "Germany", "France" };
17 |
18 | //var sliced = countries[1..^1]; // not supported by List
19 | var sliced = countries.Slice(1..^1);
20 | Assert.IsTrue(expected.SequenceEqual(sliced));
21 | }
22 |
23 | }
24 |
25 | public static class CollectionExtensions
26 | {
27 | public static IEnumerable Slice(this ICollection items, Range range)
28 | {
29 | (var offset, var count) = range.GetOffsetAndLength(items.Count);
30 | return items.Skip(offset).Take(count);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_03/chapter_15_03.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/PatternMatching1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace chapter_15_04
6 | {
7 | [TestClass]
8 | public class PatternMatching1
9 | {
10 | [TestMethod]
11 | public void TestMethod1()
12 | {
13 | Assert.AreEqual(Color.Red, ToColor(ConsoleKey.R));
14 | Assert.AreEqual(Color.Green, ToColor(ConsoleKey.G));
15 | Assert.AreEqual(Color.Blue, ToColor(ConsoleKey.B));
16 | Assert.ThrowsException(() => ToColor(ConsoleKey.Z));
17 | }
18 |
19 | public Color ToColor(ConsoleKey key) => key switch
20 | {
21 | ConsoleKey.R => Color.Red,
22 | ConsoleKey.G => Color.Green,
23 | ConsoleKey.B => Color.Blue,
24 | _ => throw new ArgumentException($"Invalid {nameof(key)}"),
25 | };
26 |
27 | public Color ToColor0(ConsoleKey key)
28 | {
29 | return key switch
30 | {
31 | ConsoleKey.R => Color.Red,
32 | ConsoleKey.G => Color.Green,
33 | ConsoleKey.B => Color.Blue,
34 | _ => throw new ArgumentException($"Invalid {nameof(key)}"),
35 | };
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/PatternMatching2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_04
5 | {
6 | [TestClass]
7 | public class PatternMatching2
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | Assert.AreEqual("string 'hello'", GetString("hello"));
13 | Assert.AreEqual("integer 0100", GetString(100));
14 | Assert.AreEqual("Fallback: 1", GetString((Int16)1));
15 | Assert.AreEqual("double 3.14", GetString(3.14));
16 | Assert.AreEqual("Fallback: 10.6", GetString(10.6m));
17 | Assert.AreEqual("Derived: a, b", GetString(new Derived("a", "b")));
18 | Assert.AreEqual("Base: x", GetString(new Base("x")));
19 | Assert.AreEqual("null", GetString(null));
20 | }
21 |
22 | private string GetString(object o) => o switch
23 | {
24 | string s => $"string '{s}'",
25 | int i => $"integer {i:d4}",
26 | double d => $"double {d:n}",
27 | Derived d => $"Derived: {d.Name}, {d.Description}",
28 | Base b => $"Base: {b.Name}",
29 | null => "null",
30 | _ => $"Fallback: {o}",
31 | };
32 |
33 | }
34 |
35 | public class Base
36 | {
37 | public Base(string name)
38 | {
39 | this.Name = name;
40 | }
41 |
42 | public string Name { get; set; }
43 | }
44 |
45 | public class Derived : Base
46 | {
47 | public Derived(string name, string description)
48 | : base(name)
49 | {
50 | this.Description = description;
51 | }
52 |
53 | public string Description { get; set; }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/PatternMatching3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace chapter_15_04
6 | {
7 | [TestClass]
8 | public class PatternMatching3
9 | {
10 | [TestMethod]
11 | public void TestMethod1()
12 | {
13 | const int len = 6;
14 | var weekDays = Enum.GetNames(typeof(DayOfWeek));
15 | var expected = new[] { "Sunday", "Monday", "Friday", };
16 |
17 | var six = weekDays
18 | .Where(w => w is string { Length: len })
19 | .ToArray();
20 |
21 | Assert.IsTrue(six.SequenceEqual(expected));
22 | }
23 |
24 | [TestMethod]
25 | public void TestMethod2()
26 | {
27 | var order = new Order()
28 | {
29 | IsMadeOnWeb = true,
30 | Quantity = 1000,
31 | Customer = new Customer()
32 | {
33 | Country = "Italy"
34 | },
35 | };
36 |
37 | Assert.AreEqual(7.5m, GetDiscount(order));
38 | order.Quantity = 1;
39 | Assert.AreEqual(5.0m, GetDiscount(order));
40 | order.IsMadeOnWeb = false;
41 | Assert.AreEqual(2.0m, GetDiscount(order));
42 | order.Customer.Country = string.Empty;
43 | Assert.AreEqual(0m, GetDiscount(order));
44 | }
45 |
46 | public decimal GetDiscount(Order order) => order switch
47 | {
48 | var o when o.Quantity > 100 => 7.5m,
49 | { IsMadeOnWeb: true } => 5.0m,
50 | { Customer: { Country: "Italy" } } => 2.0m,
51 | _ => 0,
52 | };
53 |
54 |
55 | }
56 |
57 | public class Order
58 | {
59 | public Guid Id { get; set; }
60 | public bool IsMadeOnWeb { get; set; }
61 | public Customer Customer { get; set; }
62 | public decimal Quantity { get; set; }
63 | }
64 |
65 | public class Customer
66 | {
67 | public Guid Id { get; set; }
68 | public string Name { get; set; }
69 | public string Country { get; set; }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/PatternMatching4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_04
5 | {
6 | [TestClass]
7 | public class PatternMatching4
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | Assert.IsTrue(IsOnAnyAxis(new Point(0, 10)));
13 | Assert.IsTrue(IsOnAnyAxis(new Point(10, 0)));
14 | Assert.IsTrue(IsOnAnyAxis(new Point(0, 0)));
15 | Assert.IsTrue(!IsOnAnyAxis(new Point(10, 10)));
16 | }
17 |
18 | public bool IsOnAnyAxis(Point p) => (p.X, p.Y) switch
19 | {
20 | (0, _) => true,
21 | (_, 0) => true,
22 | _ => false,
23 | };
24 |
25 | public struct Point
26 | {
27 | public Point(int x, int y)
28 | {
29 | X = x;
30 | Y = y;
31 | }
32 |
33 | public int X { get; set; }
34 | public int Y { get; set; }
35 | }
36 |
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/PatternMatching5.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_04
5 | {
6 | [TestClass]
7 | public class PatternMatching5
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | Assert.IsTrue(IsOnAxis(new Point(0, 10)));
13 | Assert.IsTrue(IsOnAxis(new Point(10, 0)));
14 | Assert.IsTrue(IsOnAxis(new Point(0, 0)));
15 | Assert.IsTrue(!IsOnAxis(new Point(10, 10)));
16 |
17 | Assert.AreEqual(SpecialPosition.YAxis, IsOnSpecialPosition(new Point(0, 10)));
18 | Assert.AreEqual(SpecialPosition.YAxis, IsOnSpecialPosition(new Point(0, -10)));
19 |
20 | Assert.AreEqual(SpecialPosition.XAxis, IsOnSpecialPosition(new Point(10, 0)));
21 | Assert.AreEqual(SpecialPosition.XAxis, IsOnSpecialPosition(new Point(-10, 0)));
22 |
23 | Assert.AreEqual(SpecialPosition.Origin, IsOnSpecialPosition(new Point(0, 0)));
24 |
25 | Assert.AreEqual(SpecialPosition.MainDiagonal, IsOnSpecialPosition(new Point(10, 10)));
26 | Assert.AreEqual(SpecialPosition.MainDiagonal, IsOnSpecialPosition(new Point(-10, -10)));
27 |
28 | Assert.AreEqual(SpecialPosition.AntiDiagonal, IsOnSpecialPosition(new Point(10, -10)));
29 | Assert.AreEqual(SpecialPosition.AntiDiagonal, IsOnSpecialPosition(new Point(-10, 10)));
30 | }
31 |
32 | public bool IsOnAxis(Point p) => p switch
33 | {
34 | (0, _) => true,
35 | (_, 0) => true,
36 | (_, _) => false,
37 | };
38 |
39 | SpecialPosition IsOnSpecialPosition(Point p) => p switch
40 | {
41 | (0, 0) => SpecialPosition.Origin,
42 | (0, _) => SpecialPosition.YAxis,
43 | (_, 0) => SpecialPosition.XAxis,
44 | var (x, y) when x == y => SpecialPosition.MainDiagonal,
45 | var (x, y) when x == -y => SpecialPosition.AntiDiagonal,
46 | _ => SpecialPosition.None,
47 | };
48 |
49 | enum SpecialPosition
50 | {
51 | None,
52 | Origin,
53 | XAxis,
54 | YAxis,
55 | MainDiagonal,
56 | AntiDiagonal,
57 | }
58 |
59 | public struct Point
60 | {
61 | public Point(int x, int y)
62 | {
63 | X = x;
64 | Y = y;
65 | }
66 |
67 | public int X { get; set; }
68 | public int Y { get; set; }
69 |
70 | public void Deconstruct(out int x, out int y)
71 | {
72 | x = X;
73 | y = Y;
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_04/chapter_15_04.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_05/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace chapter_15_05
4 | {
5 | public class Program
6 | {
7 | public static void Main()
8 | {
9 | Run1();
10 | Run2();
11 | Run3();
12 | Console.ReadKey();
13 | }
14 |
15 | static void Run1()
16 | {
17 | Console.WriteLine();
18 | Console.WriteLine("Run1");
19 | using (var x = new DisposableClass())
20 | {
21 | Console.WriteLine($"using {nameof(DisposableClass)}");
22 | } // Dispose is called
23 | }
24 |
25 | static void Run2()
26 | {
27 | Console.WriteLine();
28 | Console.WriteLine("Run2");
29 | using (var x = new Disposable1())
30 | {
31 | Console.WriteLine($"using {nameof(Disposable1)}");
32 | using (var y = new Disposable2())
33 | {
34 | Console.WriteLine($"using {nameof(Disposable2)}");
35 | using (var z = new Disposable3())
36 | {
37 | Console.WriteLine($"using {nameof(Disposable3)}");
38 | }
39 | }
40 | }
41 | }
42 |
43 | static void Run3()
44 | {
45 | Console.WriteLine();
46 | Console.WriteLine("Run3");
47 | using var x = new Disposable1();
48 | Console.WriteLine($"using {nameof(Disposable1)}");
49 |
50 | using var y = new Disposable2();
51 | Console.WriteLine($"using {nameof(Disposable2)}");
52 |
53 | using var z = new Disposable3();
54 | Console.WriteLine($"using {nameof(Disposable3)}");
55 |
56 | }// here x, y and z will be disposed
57 |
58 |
59 | }
60 |
61 | class DisposableClass : IDisposable
62 | {
63 | public void Dispose() => Console.WriteLine("== Dispose! ==");
64 | }
65 |
66 | class Disposable1 : IDisposable
67 | {
68 | public void Dispose() => Console.WriteLine("Disposable1");
69 | }
70 |
71 | class Disposable2 : IDisposable
72 | {
73 | public void Dispose() => Console.WriteLine("Disposable2");
74 | }
75 |
76 | class Disposable3 : IDisposable
77 | {
78 | public void Dispose() => Console.WriteLine("Disposable3");
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_05/chapter_15_05.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_06/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace chapter_15_06
5 | {
6 | class Program
7 | {
8 | static async Task Main(string[] args)
9 | {
10 | await SomeMethodAsync1();
11 | await SomeMethodAsync2();
12 | Console.ReadKey();
13 | }
14 |
15 | private static async Task SomeMethodAsync1()
16 | {
17 | await using (var x = new AsyncDisposableClass())
18 | {
19 | // ...
20 | }
21 | }
22 |
23 | private static async Task SomeMethodAsync2()
24 | {
25 | await using var x = new AsyncDisposableClass();
26 | // ...
27 | }
28 | }
29 |
30 | public class AsyncDisposableClass : IAsyncDisposable
31 | {
32 | public ValueTask DisposeAsync()
33 | {
34 | Console.WriteLine("Dispose called");
35 | return new ValueTask();
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_06/chapter_15_06.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_07/DisposablePattern1.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Threading.Tasks;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace chapter_15_07
6 | {
7 | ///
8 | /// This test class doesn't make any assert
9 | ///
10 | [TestClass]
11 | public class DisposablePattern1
12 | {
13 | [TestMethod]
14 | public void TestMethod1()
15 | {
16 | using var s1 = new MyRefStruct();
17 | }
18 |
19 | [TestMethod]
20 | public async Task TestMethod2()
21 | {
22 | //await using var s2 = new MyRefStruct(); // Error!
23 | }
24 |
25 | [TestMethod]
26 | public Task TestMethod3()
27 | {
28 | var s2 = new MyRefStruct();
29 | Task result;
30 | try
31 | {
32 | }
33 | finally
34 | {
35 | result = s2.DisposeAsync().AsTask();
36 | }
37 |
38 | return result;
39 | }
40 |
41 | [TestMethod]
42 | public void TestMethod4()
43 | {
44 | // dispose pattern not allowed with Dispose
45 | //using var s1 = new MyStruct();
46 | }
47 |
48 |
49 | [TestMethod]
50 | public async Task TestMethod5()
51 | {
52 | // dispose pattern allowed with DisposeAsync
53 | await using var s1 = new MyStruct();
54 |
55 | //using var s2 = new MyStruct(); // dispose pattern not allowed on Dispose
56 | }
57 |
58 | public ref struct MyRefStruct
59 | {
60 | public void Dispose() => Debug.WriteLine("Dispose");
61 | public ValueTask DisposeAsync()
62 | {
63 | Debug.WriteLine("DisposeAsync");
64 | return default(ValueTask);
65 | }
66 | }
67 |
68 | public struct MyStruct
69 | {
70 | public void Dispose() => Debug.WriteLine("Dispose");
71 | public ValueTask DisposeAsync()
72 | {
73 | Debug.WriteLine("DisposeAsync");
74 | return default(ValueTask);
75 | }
76 | }
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_07/chapter_15_07.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_08/AsyncStreams1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Threading;
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 |
9 | namespace chapter_15_08
10 | {
11 | [TestClass]
12 | public class AsyncStreams1
13 | {
14 | [TestMethod]
15 | public void TestMethod1()
16 | {
17 | var iterated = new List();
18 | foreach (var item in SyncIterator())
19 | {
20 | iterated.Add(item);
21 | }
22 | Assert.IsTrue(iterated.Count == 10);
23 | }
24 |
25 | [TestMethod]
26 | public void TestMethod2()
27 | {
28 | var iterated = new List();
29 | foreach (var item in new SyncSequence())
30 | {
31 | iterated.Add(item);
32 | }
33 | Assert.IsTrue(iterated.Count == 10);
34 | }
35 |
36 | static IEnumerable SyncIterator()
37 | {
38 | foreach (var item in Enumerable.Range(0, 10))
39 | {
40 | Thread.Sleep(500);
41 | yield return item;
42 | }
43 | }
44 |
45 | public class SyncSequence : IEnumerable
46 | {
47 | private int[] _data = Enumerable.Range(0, 10).ToArray();
48 |
49 | public IEnumerator GetEnumerator() => new SyncSequenceEnumerator(_data);
50 | IEnumerator IEnumerable.GetEnumerator() => new SyncSequenceEnumerator(_data);
51 |
52 | private class SyncSequenceEnumerator : IEnumerator, IEnumerator, IDisposable
53 | {
54 | private T[] _sequence;
55 | private int _index;
56 |
57 | public SyncSequenceEnumerator(T[] sequence)
58 | {
59 | _sequence = sequence;
60 | _index = -1;
61 | }
62 |
63 | object IEnumerator.Current => _sequence[_index];
64 | public T Current => _sequence[_index];
65 | public void Dispose() { }
66 | public void Reset() => _index = -1;
67 |
68 | public bool MoveNext()
69 | {
70 | Thread.Sleep(100);
71 | _index++;
72 | if (_sequence.Length <= _index) return false;
73 | return true;
74 | }
75 |
76 | }
77 | }
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_08/AsyncStreams2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.VisualStudio.TestTools.UnitTesting;
9 |
10 | namespace chapter_15_08
11 | {
12 | [TestClass]
13 | public class AsyncStreams2
14 | {
15 | [TestMethod]
16 | public async Task TestMethod1()
17 | {
18 | var iterated = new List();
19 | await foreach (var item in AsyncIterator())
20 | {
21 | iterated.Add(item);
22 | }
23 | Assert.IsTrue(iterated.Count == 10);
24 | }
25 |
26 | async IAsyncEnumerable AsyncIterator()
27 | {
28 | foreach (var item in Enumerable.Range(0, 10))
29 | {
30 | await Task.Delay(500);
31 | yield return item;
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_08/AsyncStreams3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.VisualStudio.TestTools.UnitTesting;
9 |
10 | namespace chapter_15_08
11 | {
12 | [TestClass]
13 | public class AsyncStreams3
14 | {
15 | [TestMethod]
16 | public async Task TestMethod1()
17 | {
18 | var iterated = new List();
19 | var sequence = new AsyncSequence();
20 | await foreach (var item in sequence)
21 | {
22 | iterated.Add(item);
23 | }
24 | Assert.IsTrue(iterated.Count == 10);
25 | }
26 |
27 | [TestMethod]
28 | public async Task TestMethod2()
29 | {
30 | var iterated = new List();
31 | var sequence = new AsyncSequence();
32 | IAsyncEnumerator enumerator = sequence.GetAsyncEnumerator();
33 | try
34 | {
35 | while (await enumerator.MoveNextAsync())
36 | {
37 | iterated.Add(enumerator.Current);
38 | }
39 | }
40 | finally { await enumerator.DisposeAsync(); }
41 | Assert.IsTrue(iterated.Count == 10);
42 | }
43 |
44 | public class AsyncSequence : IAsyncEnumerable
45 | {
46 | private int[] _data = Enumerable.Range(0, 10).ToArray();
47 | public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default)
48 | {
49 | return new MyAsyncEnumerator(_data);
50 | }
51 |
52 | private class MyAsyncEnumerator : IAsyncEnumerator
53 | {
54 | private T[] _sequence;
55 | private int _index;
56 | public MyAsyncEnumerator(T[] sequence)
57 | {
58 | _sequence = sequence;
59 | _index = -1;
60 | }
61 |
62 | public T Current => _sequence[_index];
63 | public ValueTask DisposeAsync() => default(ValueTask);
64 | public async ValueTask MoveNextAsync()
65 | {
66 | await Task.Delay(500);
67 | _index++;
68 | if (_sequence.Length <= _index) return false;
69 | return true;
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_08/AsyncStreams4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Microsoft.VisualStudio.TestTools.UnitTesting;
9 |
10 | namespace chapter_15_08
11 | {
12 | [TestClass]
13 | public class AsyncStreams4
14 | {
15 | [TestMethod]
16 | public async Task TestMethod1()
17 | {
18 | var iterated = new List();
19 | await foreach (var item in AsyncIterator().ConfigureAwait(false))
20 | {
21 | iterated.Add(item);
22 | }
23 | Assert.IsTrue(iterated.Count == 10);
24 | }
25 |
26 | async IAsyncEnumerable AsyncIterator()
27 | {
28 | foreach (var item in Enumerable.Range(0, 10))
29 | {
30 | await Task.Delay(500);
31 | yield return item;
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_08/chapter_15_08.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_09/Numbers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace chapter_15_09
6 | {
7 | public struct Numbers
8 | {
9 | private int _i;
10 |
11 | public readonly int Num0
12 | {
13 | get => _i;
14 | set { } // not useful but valid
15 | }
16 |
17 | public readonly int Num1
18 | {
19 | get => _i;
20 | //set => _i = value; // not valid
21 | }
22 |
23 | public int Num2
24 | {
25 | readonly get => _i;
26 | set => _i = value; // ok
27 | }
28 |
29 | public int Num3
30 | {
31 | get => ++_i; // strongly discouraged but it works
32 | readonly set { } // does not make sense but it works
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_09/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace chapter_15_09
4 | {
5 | class Program
6 | {
7 | static void Main(string[] args)
8 | {
9 | var v = new Vector()
10 | {
11 | x = 1,
12 | y = 3,
13 | };
14 |
15 | SomeMethod(v);
16 | ReadonlyBehavior(v);
17 | }
18 |
19 | public static float SomeMethod(in Vector vector)
20 | {
21 | // a local copy is done because GetLength is not readonly
22 | return vector.GetLength();
23 | }
24 |
25 | public static float ReadonlyBehavior(in Vector vector)
26 | {
27 | // no local copy is done because GetLengthRo is readonly
28 | return vector.GetLengthRo();
29 | }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_09/Undetected.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace chapter_15_09
6 | {
7 | struct Undetected
8 | {
9 | private IDictionary _bag;
10 | public Undetected(IDictionary bag)
11 | {
12 | _bag = bag;
13 | }
14 | public readonly string Description
15 | {
16 | get => (string)_bag["Description"];
17 | set => _bag["Description"] = value;
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_09/Vector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace chapter_15_09
6 | {
7 | public struct Vector
8 | {
9 | public float x;
10 | public float y;
11 | private readonly float SquaredRo => (x * x) + (y * y);
12 | public readonly float GetLengthRo() => MathF.Sqrt(SquaredRo);
13 | public float GetLength() => MathF.Sqrt(SquaredRo);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_09/chapter_15_09.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_10/NullCoalescing1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace chapter_15_10
6 | {
7 | [TestClass]
8 | public class NullCoalescing1
9 | {
10 | [TestMethod]
11 | public void TestMethod1()
12 | {
13 | List x = null;
14 | Accumulate(ref x, "one", "two");
15 | Accumulate(ref x, "three");
16 | Assert.IsTrue(x.Count == 3);
17 | }
18 |
19 | void Accumulate(ref List list, params string[] words)
20 | {
21 | list ??= new List();
22 | list.AddRange(words);
23 | }
24 |
25 |
26 | class Person
27 | {
28 | public Person(string firstName, string lastName, int age)
29 | {
30 | this.FirstName = firstName ?? throw new ArgumentNullException(nameof(firstName));
31 | this.LastName = lastName ?? throw new ArgumentNullException(nameof(lastName));
32 | this.Age = age;
33 | }
34 |
35 | public string FirstName { get; set; }
36 | public string LastName { get; set; }
37 | public int Age { get; set; }
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_10/chapter_15_10.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_11/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 |
4 | namespace chapter_15_11
5 | {
6 | ///
7 | /// Static local functions
8 | ///
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | var program = new Program();
14 | var person = new Person("John", "Smith", 25);
15 | program.PrintName(person);
16 | program.PrintName2(person);
17 | Console.ReadKey();
18 | }
19 |
20 | private void PrintName(Person person)
21 | {
22 | var p = person ?? throw new ArgumentNullException(nameof(person));
23 | Debug.WriteLine(Obfuscated());
24 |
25 | string Obfuscated()
26 | {
27 | if (p.Age < 18) return $"{p.FirstName[0]}. {p.LastName[0]}.";
28 | return $"{p.FirstName} {p.LastName}";
29 | }
30 | }
31 |
32 | private void PrintName2(Person person)
33 | {
34 | var p = person ?? throw new ArgumentNullException(nameof(person));
35 | Console.WriteLine(Obfuscated(p));
36 |
37 | static string Obfuscated(Person p)
38 | {
39 | if (p.Age < 18) return $"{p.FirstName[0]}. {p.LastName[0]}.";
40 | return $"{p.FirstName} {p.LastName}";
41 | }
42 | }
43 | }
44 |
45 | class Person
46 | {
47 | public Person(string firstName, string lastName, int age)
48 | {
49 | this.FirstName = firstName ?? throw new ArgumentNullException(nameof(firstName));
50 | this.LastName = lastName ?? throw new ArgumentNullException(nameof(lastName));
51 | this.Age = age;
52 | }
53 |
54 | public string FirstName { get; set; }
55 | public string LastName { get; set; }
56 | public int Age { get; set; }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_11/chapter_15_11.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_12/Interpolated1.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 |
3 | namespace chapter_15_12
4 | {
5 | [TestClass]
6 | public class Interpolated1
7 | {
8 | [TestMethod]
9 | public void TestMethod1()
10 | {
11 | string s1 = "c:\\temp";
12 | string s2 = @"c:\temp";
13 | Assert.AreEqual(s1, s2);
14 |
15 | var folder = "temp";
16 | var s3 = $"The path for {folder} is c:\\{folder}";
17 | var s4 = $@"The path for {folder} is c:\{folder}";
18 | Assert.AreEqual(s3, s4);
19 | var s5 = @$"The path for {folder} is c:\{folder}";
20 | Assert.AreEqual(s3, s5);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_12/chapter_15_12.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_13/StackAlloc1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace chapter_15_13
5 | {
6 | [TestClass]
7 | public class StackAlloc1
8 | {
9 | [TestMethod]
10 | public void TestMethod1()
11 | {
12 | string input = " this string can be trimmed \r\n";
13 | var expected = "this string can be trimmed";
14 | ReadOnlySpan trimmedSpan = input.AsSpan().Trim(stackalloc[] { ' ', '\r', '\n' });
15 | string result = trimmedSpan.ToString();
16 | Assert.AreEqual(expected, result);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_13/chapter_15_13.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_14/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace chapter_15_14
4 | {
5 | ///
6 | /// Unmanaged constructed types
7 | ///
8 | class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | Span> records1 = stackalloc Header[10];
13 | Span> records2 = stackalloc Header[10];
14 | }
15 |
16 | struct Header
17 | {
18 | T Word1;
19 | T Word2;
20 | T Word3;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/chapter_15/chapter_15_14/chapter_15_14.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/chapter_17/chapter_17_lib/Rectangle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace chapter_17_lib
4 | {
5 | public struct Rectangle
6 | {
7 | public readonly int Left;
8 | public readonly int Top;
9 | public readonly int Right;
10 | public readonly int Bottom;
11 |
12 | public int Width => Right - Left;
13 | public int Height => Bottom - Top;
14 |
15 | public int Area => Width * Height;
16 |
17 | public Rectangle(int left, int top, int right, int bottom)
18 | {
19 | Left = left;
20 | Top = top;
21 | Right = right;
22 | Bottom = bottom;
23 | }
24 |
25 | public static Rectangle Empty => new Rectangle(0, 0, 0, 0);
26 | }
27 |
28 | public static class RectangleExtensions
29 | {
30 | public static Rectangle Inflate(this Rectangle r, int left, int top, int right, int bottom) =>
31 | new Rectangle(r.Left + left, r.Top + top, r.Right + right, r.Bottom + bottom);
32 |
33 | public static Rectangle Deflate(this Rectangle r, int left, int top, int right, int bottom) =>
34 | new Rectangle(r.Left - left, r.Top - top, r.Right - right, r.Bottom - bottom);
35 |
36 | public static Rectangle Intersect(this Rectangle a, Rectangle b)
37 | {
38 | int l = Math.Max(a.Left, b.Left);
39 | int r = Math.Min(a.Right, b.Right);
40 | int t = Math.Max(a.Top, b.Top);
41 | int bt = Math.Min(a.Bottom, b.Bottom);
42 |
43 | if (r >= l && bt >= t)
44 | return new Rectangle(l, t, r, bt);
45 |
46 | return Rectangle.Empty;
47 | }
48 |
49 | public static bool IntersectsWith(this Rectangle a, Rectangle b) =>
50 | ((b.Left < a.Right) && (a.Left < b.Right)) &&
51 | ((b.Top < a.Bottom) && (a.Top < b.Bottom));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/chapter_17/chapter_17_lib/chapter_17_lib.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/chapter_17/chapter_17_tests/DemoTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 |
3 | namespace chapter_17_tests
4 | {
5 | [TestClass]
6 | public class UnitTestsClass
7 | {
8 | [AssemblyInitialize]
9 | public static void AssemblyInit(TestContext context)
10 | {
11 | context.WriteLine("Assembly init...");
12 | }
13 |
14 | [AssemblyCleanup]
15 | public static void AssemblyCleanup()
16 | {
17 | }
18 |
19 | [ClassInitialize]
20 | public static void TestFixtureSetup(TestContext context)
21 | {
22 | context.WriteLine("Fixture setup...");
23 | }
24 |
25 | [ClassCleanup]
26 | public static void TestFixtureTearDown()
27 | {
28 | }
29 |
30 | [TestInitialize]
31 | public void Setup()
32 | {
33 | }
34 |
35 | [TestCleanup]
36 | public void TearDown()
37 | {
38 | }
39 |
40 | [TestMethod]
41 | public void TestMethod1()
42 | {
43 | }
44 |
45 | [TestMethod]
46 | public void TestMethod2()
47 | {
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/chapter_17/chapter_17_tests/RectangleDataDrivenTests.cs:
--------------------------------------------------------------------------------
1 | using chapter_17_lib;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System.Collections.Generic;
4 |
5 | namespace chapter_17_tests
6 | {
7 | [TestClass]
8 | public class RectangleDataDrivenTests
9 | {
10 | [DataTestMethod]
11 | [DataRow(true, 3, 4, 5, 6)]
12 | [DataRow(true, 5, 10, 20, 13)]
13 | [DataRow(false, 11, 13, 15, 16)]
14 | public void TestIntersectsWith_DataRows(bool result, int left, int top, int right, int bottom)
15 | {
16 | var rectangle = new Rectangle(1, 2, 10, 12);
17 |
18 | Assert.AreEqual(
19 | result,
20 | rectangle.IntersectsWith(
21 | new Rectangle(left, top, right, bottom)));
22 | }
23 |
24 | public static IEnumerable