├── FinalizeVsDispose ├── input.txt ├── DisposeVsFinalize.csproj └── Program.cs ├── UsingKeyword ├── Person1.cs ├── Person2.cs ├── UsingKeyword.csproj └── Program.cs ├── .gitignore ├── NuGet ├── Program.cs └── NuGet.csproj ├── IsVsAs ├── IsVsAs.csproj └── Program.cs ├── Events ├── Events.csproj └── Program.cs ├── Record ├── Record.csproj └── Program.cs ├── Attributes ├── Attributes.csproj └── Program.cs ├── Cohesion ├── Cohesion.csproj └── Program.cs ├── Coupling ├── Coupling.csproj └── Program.cs ├── Delegates ├── Delegates.csproj └── Program.cs ├── Indexers ├── Indexers.csproj └── Program.cs ├── Reflection ├── Reflection.csproj └── Program.cs ├── Strategy ├── Strategy.csproj └── Program.cs ├── Collections ├── Collections.csproj └── Program.cs ├── GetHashCode ├── GetHashCode.csproj └── Program.cs ├── AnonymousTypes ├── AnonymousTypes.csproj └── Program.cs ├── CatchException ├── CatchException.csproj └── Program.cs ├── CheckedKeyword ├── CheckedKeyword.csproj └── Program.cs ├── DebugVsRelease ├── DebugVsRelease.csproj └── Program.cs ├── Deconstruction ├── Deconstruction.csproj └── Program.cs ├── DoubleVsDecimal ├── DoubleVsDecimal.csproj └── Program.cs ├── ImmutableTypes ├── ImmutableTypes.csproj └── Program.cs ├── PatternMatching ├── PatternMatching.csproj └── Program.cs ├── Serialization ├── Serialization.csproj └── Program.cs ├── TemplateMethod ├── TemplateMethod.csproj └── Program.cs ├── ThrowVsThrowEx ├── ThrowVsThrowEx.csproj └── Program.cs ├── TypeofVsGetType ├── TypeofVsGetType.csproj └── Program.cs ├── CollectionsArray ├── CollectionsArray.csproj └── Program.cs ├── CollectionsLists ├── CollectionsLists.csproj └── Program.cs ├── DecoratorPattern ├── DecoratorPattern.csproj └── Program.cs ├── TupleVsValueTuple ├── TupleVsValueTuple.csproj └── Program.cs ├── DependencyInjection ├── DependencyInjection.csproj └── Program.cs ├── InversionOfControl ├── InversionOfControl.csproj └── Program.cs ├── OperatorOverloading ├── OperatorOverloading.csproj └── Program.cs ├── StringImmutability ├── StringImmutability.csproj └── Program.cs ├── CheckedPerformanceTest ├── CheckedPerformanceTest.csproj └── Program.cs ├── CollectionsArrayLists ├── CollectionsArrayLists.csproj └── Program.cs ├── CollectionsDictionary ├── CollectionsDictionary.csproj └── Program.cs ├── ObserverDesignPattern ├── ObserverDesignPattern.csproj └── Program.cs ├── PreprocessorDirectives ├── PreprocessorDirectives.csproj └── Program.cs ├── StringVsStringBuilder ├── StringVsStringBuilder.csproj └── Program.cs ├── ExpressionBodiedMembers ├── ExpressionBodiedMembers.csproj └── Program.cs ├── FuncsAndLambdaExpressions ├── FuncsAndLambdaExpressions.csproj └── Program.cs ├── GarbageCollectorAlgorithm ├── GarbageCollectorAlgorithm.csproj └── Program.cs ├── DefaultInterfaceImplementation ├── DefaultInterfaceImplementation.csproj └── Program.cs ├── DoubleVsDecimalPerformanceTest ├── DoubleVsDecimalPerformanceTest.csproj └── Program.cs ├── InversionOfControl_ConsoleApp ├── InversionOfControl_ConsoleApp.csproj └── Program.cs ├── StringVsStringBuilderPerformanceTest ├── StringVsStringBuilderPerformanceTest.csproj └── Program.cs ├── CompositionOverInheritance_Composition ├── CompositionOverInheritance_Composition.csproj └── Program.cs ├── CompositionOverInheritance_Inheritance ├── CompositionOverInheritance_Inheritance.csproj └── Program.cs ├── CompositionOverInheritance_GoodInheritance ├── CompositionOverInheritance_GoodInheritance.csproj └── Program.cs ├── InversionOfControl_WinFormsApp ├── InversionOfControl_WinFormsApp.csproj ├── Program.cs ├── HelloForm.cs ├── HelloForm.resx └── HelloForm.Designer.cs ├── DynamicKeyword ├── DynamicKeyword.csproj └── Program.cs ├── Caching ├── Caching.csproj └── Program.cs ├── TemplateMethod_UnitTests ├── TemplateMethod_UnitTests.csproj └── Program.cs ├── KeywordsCausingTestabilityIssues ├── KeywordsCausingTestabilityIssues.csproj └── Program.cs ├── README.md ├── Mocks ├── Mocks.csproj └── Mocks.cs ├── NullableReferenceTypes ├── NullableReferenceTypes.csproj └── Program.cs └── 50InterviewQuestionsMid.sln /FinalizeVsDispose/input.txt: -------------------------------------------------------------------------------- 1 | Hello from line1! 2 | Hello from line2! 3 | Bye bye! -------------------------------------------------------------------------------- /UsingKeyword/Person1.cs: -------------------------------------------------------------------------------- 1 | namespace DomainObjects 2 | { 3 | internal class Person 4 | { 5 | private Stopwatch _stopwatch; 6 | public string Name { get; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj 2 | [Bb]in 3 | *.user 4 | *.suo 5 | *.[Cc]ache 6 | *.bak 7 | *.ncb 8 | *.log 9 | *.v2 10 | *.DS_Store 11 | [Tt]humbs.db 12 | _ReSharper.* 13 | *.resharper 14 | Ankh.NoLoad 15 | .vs -------------------------------------------------------------------------------- /UsingKeyword/Person2.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace DTOs 4 | { 5 | internal class Person 6 | { 7 | [JsonPropertyName("name")] 8 | public string Name { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NuGet/Program.cs: -------------------------------------------------------------------------------- 1 | using Moq; 2 | using NUnit.Framework; 3 | 4 | Console.ReadKey(); 5 | 6 | public interface IFlyable 7 | { 8 | public void Fly(); 9 | } 10 | 11 | [TestFixture] 12 | public class Tests 13 | { 14 | private Mock _flyableMock; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /IsVsAs/IsVsAs.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Events/Events.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Record/Record.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Attributes/Attributes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Cohesion/Cohesion.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Coupling/Coupling.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Delegates/Delegates.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Indexers/Indexers.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Reflection/Reflection.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Strategy/Strategy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Collections/Collections.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GetHashCode/GetHashCode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /UsingKeyword/UsingKeyword.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AnonymousTypes/AnonymousTypes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CatchException/CatchException.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CheckedKeyword/CheckedKeyword.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DebugVsRelease/DebugVsRelease.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Deconstruction/Deconstruction.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DoubleVsDecimal/DoubleVsDecimal.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ImmutableTypes/ImmutableTypes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PatternMatching/PatternMatching.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Serialization/Serialization.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TemplateMethod/TemplateMethod.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ThrowVsThrowEx/ThrowVsThrowEx.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TypeofVsGetType/TypeofVsGetType.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CollectionsArray/CollectionsArray.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CollectionsLists/CollectionsLists.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DecoratorPattern/DecoratorPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TupleVsValueTuple/TupleVsValueTuple.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DependencyInjection/DependencyInjection.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /InversionOfControl/InversionOfControl.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OperatorOverloading/OperatorOverloading.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /StringImmutability/StringImmutability.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CheckedPerformanceTest/CheckedPerformanceTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CollectionsArrayLists/CollectionsArrayLists.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CollectionsDictionary/CollectionsDictionary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ObserverDesignPattern/ObserverDesignPattern.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PreprocessorDirectives/PreprocessorDirectives.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /StringVsStringBuilder/StringVsStringBuilder.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ExpressionBodiedMembers/ExpressionBodiedMembers.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FuncsAndLambdaExpressions/FuncsAndLambdaExpressions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GarbageCollectorAlgorithm/GarbageCollectorAlgorithm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GarbageCollectorAlgorithm/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | bool flag = true; 3 | Person person = new Person(); 4 | if(flag) 5 | { 6 | string textInsideIf = "aaa"; 7 | person.Name = "Tom"; 8 | } 9 | 10 | string text = "bbb"; 11 | 12 | 13 | Console.ReadKey(); 14 | 15 | class Person 16 | { 17 | public string Name { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /DefaultInterfaceImplementation/DefaultInterfaceImplementation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DoubleVsDecimalPerformanceTest/DoubleVsDecimalPerformanceTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /InversionOfControl_ConsoleApp/InversionOfControl_ConsoleApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /StringVsStringBuilderPerformanceTest/StringVsStringBuilderPerformanceTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CompositionOverInheritance_Composition/CompositionOverInheritance_Composition.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CompositionOverInheritance_Inheritance/CompositionOverInheritance_Inheritance.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CompositionOverInheritance_GoodInheritance/CompositionOverInheritance_GoodInheritance.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /InversionOfControl_WinFormsApp/InversionOfControl_WinFormsApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | enable 7 | true 8 | enable 9 | 10 | 11 | -------------------------------------------------------------------------------- /DynamicKeyword/DynamicKeyword.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Caching/Caching.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /InversionOfControl_ConsoleApp/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine("Hello! What's your name?"); 2 | var name = Console.ReadLine(); 3 | int yearOfBirth; 4 | do 5 | { 6 | Console.WriteLine("What year you were born?"); 7 | } 8 | while (!int.TryParse(Console.ReadLine(), out yearOfBirth)); 9 | 10 | Console.WriteLine( 11 | $"Hello {name}, you are " + 12 | $"{DateTime.Now.Year - yearOfBirth} years old!"); 13 | 14 | Console.ReadKey(); 15 | 16 | -------------------------------------------------------------------------------- /TemplateMethod_UnitTests/TemplateMethod_UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /InversionOfControl_WinFormsApp/Program.cs: -------------------------------------------------------------------------------- 1 | namespace InversionOfControl_WinFormsApp 2 | { 3 | internal static class Program 4 | { 5 | /// 6 | /// The main entry point for the application. 7 | /// 8 | [STAThread] 9 | static void Main() 10 | { 11 | ApplicationConfiguration.Initialize(); 12 | Application.Run(new HelloForm()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /KeywordsCausingTestabilityIssues/KeywordsCausingTestabilityIssues.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /NuGet/NuGet.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 50InterviewQuestionsMid 2 | 3 | Hello! 4 | 5 | My name is Krystyna and welcome to my GitHub. 6 | 7 | This repository is part of my "C#/.NET - 50 Essential Interview Questions (Mid Level)" course, which you can find under this link: 8 | 9 | ## FAQ: 10 | 11 | ### Q1: How do I download the files? 12 | A: If you're not familiar with GitHub and just want to download the entire solution, click the green button saying "Code", and then select the "Download ZIP". 13 | -------------------------------------------------------------------------------- /FinalizeVsDispose/DisposeVsFinalize.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | Always 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Collections/Program.cs: -------------------------------------------------------------------------------- 1 | var strings = new string[5]; 2 | strings[0] = "hello"; 3 | //this would thrown an IndexOutOfRangeException 4 | //strings[10] = "this is not going to work"; 5 | 6 | var numbers = new[] { 1, 2, 3 }; 7 | var twoDimensionalArray = new int[3,5]; 8 | twoDimensionalArray[1, 2] = 10; 9 | 10 | var jaggedArray = new[] 11 | { 12 | new[] { 1, 2, 3 }, 13 | new[] { 1 }, 14 | new[] { 1, 2 }, 15 | }; 16 | jaggedArray[2][1] = 5; 17 | 18 | 19 | Console.ReadKey(); 20 | -------------------------------------------------------------------------------- /DebugVsRelease/Program.cs: -------------------------------------------------------------------------------- 1 | public class Program 2 | { 3 | public static void Main(string[] args) 4 | { 5 | #if DEBUG 6 | Console.WriteLine("We are in Debug mode!"); 7 | #endif 8 | 9 | #if RELEASE 10 | Console.WriteLine("We are in Release mode!"); 11 | #endif 12 | 13 | int someUnusedVariable = 5; 14 | const string Hello = "Hello!"; 15 | Console.WriteLine(Hello + Hello); 16 | Console.ReadKey(); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Mocks/Mocks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /NullableReferenceTypes/NullableReferenceTypes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /CollectionsArray/Program.cs: -------------------------------------------------------------------------------- 1 | var array = new int[5]; //this array will hold 5 zeros 2 | //array[10] = 7; //this will throw an IndexOutOfRangeException 3 | 4 | var stringsArray = new [] {"a", "b", "c"}; 5 | 6 | //single-dimensional array filled with defaults (0s in case of int) 7 | var numbers = new int[5]; 8 | 9 | //two-dimensional array 10 | var matrix = new int[3, 5]; 11 | matrix[1, 1] = 10; 12 | 13 | //jagged array 14 | var jagged = new int[3][]; 15 | jagged[0] = new int[2]; 16 | jagged[1] = new int[1]; 17 | jagged[2] = new int[3]; 18 | 19 | jagged[2][1] = 7; 20 | 21 | Console.ReadKey(); 22 | -------------------------------------------------------------------------------- /DoubleVsDecimal/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine("Double:"); 2 | Console.WriteLine("0.3d == (0.1d + 0.2d): " + (0.3d == (0.1d + 0.2d))); 3 | 4 | Console.WriteLine("\nDecimal:"); 5 | Console.WriteLine("0.3m == (0.1m + 0.2m): " + (0.3m == (0.1m + 0.2m))); 6 | 7 | Console.WriteLine("\nAreEqual(1d, 1.0000000001d, 0.000000001d)"); 8 | Console.WriteLine(AreEqual(1d, 1.0000000001d, 0.000000001d)); 9 | 10 | Console.WriteLine("\nAreEqual(1d, 1.0000000001d, 0.0000000001d)"); 11 | Console.WriteLine(AreEqual(1d, 1.0000000001d, 0.0000000001d)); 12 | Console.ReadKey(); 13 | 14 | //when checking doubles for equality, we should check if 15 | //the difference between them is smaller than some tolerance 16 | bool AreEqual(double a, double b, double tolerance) 17 | { 18 | return Math.Abs(a - b) < tolerance; 19 | } 20 | -------------------------------------------------------------------------------- /StringVsStringBuilder/Program.cs: -------------------------------------------------------------------------------- 1 | //string is immutable, so every modification actually creates a new string 2 | using System.Text; 3 | 4 | var someString = "abc"; 5 | someString = "def"; 6 | someString += "g"; 7 | Console.WriteLine("someString is " + someString); 8 | 9 | //if result is not built incrementally but in one instruction, stick to simple string: 10 | var firstName = "John"; 11 | var lastName = "Smith"; 12 | string name1 = firstName + " " + lastName; 13 | //behind the scenes it actually gets translated to: 14 | string name = String.Concat(firstName, " ", lastName); 15 | 16 | //this is not only uglier but actually slower: 17 | StringBuilder builder = new StringBuilder(); 18 | builder.Append(firstName); 19 | builder.Append(" "); 20 | builder.Append(lastName); 21 | string name2 = builder.ToString(); 22 | 23 | Console.ReadLine(); 24 | -------------------------------------------------------------------------------- /CollectionsArrayLists/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | //we can have different types in single ArrayList 4 | var arrayList = new ArrayList() { 5 | 1, "hello", new DateTime(2022, 1, 1) }; 6 | 7 | var numbers = new ArrayList() { 1, 2, 3 }; 8 | var strings = new ArrayList() { "a", "b", "c" }; 9 | 10 | Console.ReadKey(); 11 | 12 | int Sum(ArrayList hopefullyNumbers) 13 | { 14 | int result = 0; 15 | foreach (var number in hopefullyNumbers) 16 | { 17 | try 18 | { 19 | //we are not sure if those objects are ints 20 | //so we try to cast, but in try-catch in case 21 | result += (int)number; 22 | } 23 | catch (InvalidCastException) 24 | { 25 | Console.WriteLine($"{number} is not really an int!"); 26 | throw; 27 | } 28 | } 29 | return result; 30 | } -------------------------------------------------------------------------------- /TypeofVsGetType/Program.cs: -------------------------------------------------------------------------------- 1 | var type1 = typeof(Base); 2 | Console.WriteLine("type1: " + type1.FullName); 3 | 4 | var baseObj = new Base(); 5 | var type2 = baseObj.GetType(); 6 | Console.WriteLine("type2: " + type2.FullName); 7 | 8 | Derived derived = new Derived(); 9 | var type3 = derived.GetType(); 10 | Console.WriteLine("type3: " + type3.FullName); 11 | 12 | Base derivedAsBase = new Derived(); 13 | var type4 = derivedAsBase.GetType(); 14 | Console.WriteLine("type4: " + type4.FullName); 15 | 16 | Console.WriteLine(); 17 | 18 | PrintTypeName(derived); 19 | 20 | string text = "abc"; 21 | PrintTypeName(text); 22 | 23 | Console.ReadKey(); 24 | 25 | void PrintTypeName(object obj) 26 | { 27 | var type = obj.GetType(); 28 | Console.WriteLine("type name is: " + type.FullName); 29 | } 30 | 31 | class Base 32 | { 33 | 34 | } 35 | 36 | class Derived : Base 37 | { 38 | 39 | } -------------------------------------------------------------------------------- /UsingKeyword/Program.cs: -------------------------------------------------------------------------------- 1 | global using System.Diagnostics; 2 | 3 | using PersonDTO = DTOs.Person; 4 | using PersonDomain = DomainObjects.Person; 5 | using static System.Console; 6 | using System.Text; 7 | 8 | var stopwatch = new Stopwatch(); 9 | 10 | var personDTO = new PersonDTO(); 11 | var domainPerson = new PersonDomain(); 12 | 13 | WriteLine("Hello!"); 14 | WriteLine("How"); 15 | WriteLine("are"); 16 | WriteLine("you?"); 17 | 18 | FileStream fileStream1 = File.Open("some path", FileMode.Open); 19 | try 20 | { 21 | //some operations 22 | } 23 | finally 24 | { 25 | fileStream1.Dispose(); 26 | } 27 | 28 | using(var fileStream2 = File.Open("some path", FileMode.Open)) 29 | { 30 | //some operations 31 | } 32 | 33 | //this is possible staring with C# 8 34 | 35 | using var fileStream3 = File.Open("some path", FileMode.Open); 36 | //some operations 37 | 38 | ReadLine(); -------------------------------------------------------------------------------- /Reflection/Program.cs: -------------------------------------------------------------------------------- 1 | var converter = new ObjectToTextConverter(); 2 | 3 | Console.WriteLine(converter.Convert( 4 | new House("123 Maple Road, Berrytown", 170.6d, 2))); 5 | 6 | Console.WriteLine(converter.Convert( 7 | new Pet("Taiga", PetType.Dog, 30))); 8 | 9 | Console.ReadKey(); 10 | 11 | class ObjectToTextConverter 12 | { 13 | public string Convert(object obj) 14 | { 15 | Type type = obj.GetType(); 16 | 17 | var properties = type 18 | .GetProperties() 19 | .Where(property => property.Name != "EqualityContract"); 20 | 21 | return string.Join( 22 | ", ", 23 | properties 24 | .Select(property => 25 | $"{property.Name} is {property.GetValue(obj)}")); 26 | } 27 | } 28 | 29 | public record Pet(string Name, PetType PetType, float Weight); 30 | public record House(string Adderss, double Area, int Floors); 31 | public enum PetType {Cat, Dog, Fish} -------------------------------------------------------------------------------- /KeywordsCausingTestabilityIssues/Program.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | public interface IDatabaseConnection 4 | { 5 | Person GetById(int personId); 6 | void CreateNew(Person person); 7 | void Update(Person person); 8 | } 9 | 10 | public class Person 11 | { 12 | public int? Id { get; } 13 | public int Name { get; } 14 | } 15 | 16 | public class PersonController 17 | { 18 | private IDatabaseConnection _databaseConnection; 19 | 20 | public PersonController(IDatabaseConnection databaseConnection) 21 | { 22 | _databaseConnection = databaseConnection; 23 | } 24 | 25 | public Person GetById(int personId) 26 | { 27 | return _databaseConnection.GetById(personId); 28 | } 29 | 30 | public void Person(Person person) 31 | { 32 | if(person.Id == null) 33 | { 34 | _databaseConnection.CreateNew(person); 35 | } 36 | else 37 | { 38 | _databaseConnection.Update(person); 39 | } 40 | } 41 | } 42 | 43 | [TestFixture] 44 | public class PersonControllerTests 45 | { 46 | [Test] 47 | public void 48 | } -------------------------------------------------------------------------------- /DoubleVsDecimalPerformanceTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | int iterations = 30000000; 4 | var resultForDouble = DoubleTest(iterations); 5 | var resultForDecimal = DecimalTest(iterations); 6 | 7 | Console.WriteLine($"Calculation of {iterations} elements for " + 8 | $"double took { resultForDouble } ticks while for " + 9 | $"decimal it took {resultForDecimal}"); 10 | Console.WriteLine($"Decimal took {(((double)resultForDecimal / (double)resultForDouble) - 1d) * 100}% longer"); 11 | 12 | Console.ReadKey(); 13 | 14 | 15 | long DoubleTest(int iterations) 16 | { 17 | Stopwatch stopwatch = Stopwatch.StartNew(); 18 | double z = 0; 19 | for (int i = 0; i < iterations; i++) 20 | { 21 | double x = i; 22 | double y = x * i; 23 | z += y; 24 | } 25 | stopwatch.Stop(); 26 | return stopwatch.ElapsedTicks; 27 | } 28 | 29 | long DecimalTest(int iterations) 30 | { 31 | Stopwatch stopwatch = Stopwatch.StartNew(); 32 | decimal z = 0; 33 | for (int i = 0; i < iterations; i++) 34 | { 35 | decimal x = i; 36 | decimal y = x * i; 37 | z += y; 38 | } 39 | stopwatch.Stop(); 40 | return stopwatch.ElapsedTicks; 41 | } -------------------------------------------------------------------------------- /FinalizeVsDispose/Program.cs: -------------------------------------------------------------------------------- 1 | using var fileReader = new FileReader("input.txt"); 2 | var line1 = fileReader.ReadLine(); 3 | var line2 = fileReader.ReadLine(); 4 | 5 | //below we trigger the destruction 6 | //of the john object from the SomeMethod method 7 | SomeMethod(); 8 | 9 | GC.Collect(); 10 | Console.ReadKey(); 11 | 12 | void SomeMethod() 13 | { 14 | var john = new Person("John"); 15 | } 16 | 17 | class Person 18 | { 19 | string Name { get; } 20 | public Person(string name) => Name = name; 21 | ~Person() 22 | { 23 | Console.WriteLine($"Person {Name} is being destructed"); 24 | } 25 | 26 | //we can't declare the Finalize method, we must use the destructor 27 | //protected override void Finalize() 28 | //{ 29 | 30 | //} 31 | } 32 | 33 | class FileReader : IDisposable 34 | { 35 | private StreamReader? _streamReader; 36 | private readonly string _path; 37 | 38 | public FileReader(string path) 39 | { 40 | _path = path; 41 | } 42 | 43 | public string ReadLine() 44 | { 45 | _streamReader ??= new StreamReader(_path); 46 | return _streamReader.ReadLine(); 47 | } 48 | 49 | public void Dispose() 50 | { 51 | _streamReader?.Dispose(); 52 | } 53 | } -------------------------------------------------------------------------------- /PreprocessorDirectives/Program.cs: -------------------------------------------------------------------------------- 1 | #define MY_SYMBOL 2 | #if MY_SYMBOL 3 | Console.WriteLine("MY_SYMBOL is defined"); 4 | #endif 5 | 6 | #if (DEBUG && NET5_0_OR_GREATER) 7 | Console.WriteLine("We are in Debug mode in .NET 5 or greater."); 8 | #elif (DEBUG && !NET5_0_OR_GREATER) 9 | Console.WriteLine("We are in Debug mode in .NET older than 5."); 10 | #elif (RELEASE && NET6_0_IOS) 11 | Console.WriteLine("We are in Release mode and we target iOS."); 12 | #endif 13 | 14 | #region someCollapsibleCode 15 | Console.WriteLine("Not much going on here"); 16 | Console.WriteLine("..."); 17 | Console.WriteLine("..."); 18 | #endregion 19 | 20 | #warning this method is deprecated, use NewMethod instead 21 | OldMethod(); 22 | 23 | try 24 | { 25 | //some code that can throw 26 | } 27 | catch (Exception ex) 28 | { 29 | #pragma warning disable CA2200 30 | throw ex; 31 | #pragma warning restore CA2200 32 | } 33 | 34 | #nullable disable 35 | string nullable = null; 36 | #nullable enable 37 | Console.WriteLine(nullable); 38 | 39 | Console.ReadKey(); 40 | 41 | void OldMethod() 42 | { 43 | Console.WriteLine( 44 | "This method shouldn't be used, use NewMethod instead"); 45 | } 46 | 47 | void NewMethod() 48 | { 49 | Console.WriteLine("Brand new method"); 50 | } 51 | -------------------------------------------------------------------------------- /CompositionOverInheritance_GoodInheritance/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | Console.ReadLine(); 3 | 4 | public class Person 5 | { 6 | public string FirstName { get; } 7 | public string LastName { get; } 8 | public int YearOfBirth { get; } 9 | 10 | public Person(string firstName, string lastName, int yearOfBirth) 11 | { 12 | FirstName = firstName; 13 | LastName = lastName; 14 | YearOfBirth = yearOfBirth; 15 | } 16 | } 17 | 18 | public class Employee : Person 19 | { 20 | public Employee( 21 | string firstName, 22 | string lastName, 23 | int yearOfBirth, 24 | string position) : 25 | base(firstName, lastName, yearOfBirth) 26 | { 27 | Position = position; 28 | } 29 | 30 | public string Position { get; } 31 | } 32 | 33 | //in this case using composition is awkward 34 | public class ComposedEmployee 35 | { 36 | private Person _person; 37 | public string FirstName => _person.FirstName; 38 | public string LastName => _person.LastName; 39 | public int YearOfBirth => _person.YearOfBirth; 40 | public string Position { get; } 41 | 42 | public ComposedEmployee(Person person, string position) 43 | { 44 | _person = person; 45 | Position = position; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /DynamicKeyword/Program.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Hosting; 2 | 3 | dynamic text = "Some text"; 4 | 5 | //this will compile, but will fail at runtime 6 | //text.ThisMethodDoesNotExistInStringType(); 7 | 8 | //the below variable is also of type dynamic 9 | var textToUpper = text.ToUpper(); 10 | 11 | //casting can be used to "unwrap" the actual type from the dynamic variable 12 | //implicitly... 13 | string actualText = text; 14 | 15 | //or explicitly... 16 | string actualTextExplicitCast = (string)text; 17 | 18 | var someClass = new SomeClass(text); 19 | 20 | Console.WriteLine(RunPython()); 21 | 22 | Console.ReadKey(); 23 | 24 | dynamic RunPython() 25 | { 26 | const string pythonScript = 27 | @"class PythonClass: 28 | def toUpper(self, input): 29 | return input.upper()"; 30 | 31 | var engine = Python.CreateEngine(); 32 | var scope = engine.CreateScope(); 33 | var operations = engine.Operations; 34 | 35 | engine.Execute(pythonScript, scope); 36 | var pythonClassObj = scope.GetVariable("PythonClass"); 37 | dynamic instance = operations.CreateInstance(pythonClassObj); 38 | 39 | return instance.toUpper("Hello!"); 40 | } 41 | 42 | class SomeClass 43 | { 44 | public string Text { get; } 45 | public SomeClass(dynamic hopefullyText) 46 | { 47 | Text = hopefullyText; 48 | } 49 | } -------------------------------------------------------------------------------- /StringVsStringBuilderPerformanceTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text; 3 | 4 | int iterations = 100000; 5 | var (resultForString, text) = StringTest(iterations); 6 | 7 | var (resultForStringBuilder, textBuiltByStringBuilder) = StringBuilderTest(iterations); 8 | 9 | Console.WriteLine($"Concatenation of {iterations} strings for " + 10 | $"string took { resultForString } ticks while for " + 11 | $"StringBuilder it took {resultForStringBuilder}"); 12 | Console.WriteLine($"string took {(((double)resultForString / (double)resultForStringBuilder) - 1d) * 100}% longer"); 13 | Console.WriteLine("Are results equal? " + (text == textBuiltByStringBuilder)); 14 | Console.ReadKey(); 15 | 16 | (long, string) StringTest(int iterations) 17 | { 18 | Stopwatch stopWatch = Stopwatch.StartNew(); 19 | string a = ""; 20 | for (int i = 0; i < iterations; i++) 21 | { 22 | a += "a"; 23 | } 24 | stopWatch.Stop(); 25 | return (stopWatch.ElapsedTicks, a); 26 | } 27 | 28 | (long, string) StringBuilderTest(int iterations) 29 | { 30 | Stopwatch stopWatch = Stopwatch.StartNew(); 31 | StringBuilder a = new StringBuilder(); 32 | for (int i = 0; i < iterations; i++) 33 | { 34 | a.Append("a"); 35 | } 36 | stopWatch.Stop(); 37 | return (stopWatch.ElapsedTicks, a.ToString()); 38 | } -------------------------------------------------------------------------------- /Coupling/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | Console.ReadKey(); 3 | 4 | public record Subscriber(string Email, bool IsPremium); 5 | 6 | public class Subscribers 7 | { 8 | //public Subscriber[] Items; 9 | public IEnumerable Items => _items; //we expose an abstract collection 10 | private HashSet _items { get; } 11 | public Subscribers(HashSet items) => _items = items; 12 | } 13 | 14 | public class NewsletterSender 15 | { 16 | private Subscribers _subscribers; 17 | 18 | public NewsletterSender(Subscribers subscribers) 19 | { 20 | _subscribers = subscribers; 21 | } 22 | 23 | public void SendTo(bool premiumSubscribersOnly) 24 | { 25 | foreach (var subscriber in _subscribers.Items.Where(s => 26 | !premiumSubscribersOnly || s.IsPremium)) 27 | { 28 | Console.WriteLine($"Newsletter sent to {subscriber.Email}"); 29 | } 30 | } 31 | 32 | //this worked for array only 33 | //public void SendTo(bool premiumSubscribersOnly) 34 | //{ 35 | // for (int i = 0; i < _subscribers.Items.Length; i++) 36 | // { 37 | // if (!premiumSubscribersOnly || 38 | // _subscribers.Items[i].IsPremium) 39 | // { 40 | // Console.WriteLine( 41 | // $"Newsletter sent to " + 42 | // $"{_subscribers.Items[i].Email}"); 43 | // } 44 | // } 45 | //} 46 | } 47 | -------------------------------------------------------------------------------- /GetHashCode/Program.cs: -------------------------------------------------------------------------------- 1 | var anyObject1 = "abc"; 2 | Console.WriteLine( 3 | $"'{anyObject1}' hashcode is {anyObject1.GetHashCode()}"); 4 | 5 | var anyObject2 = 123; 6 | Console.WriteLine( 7 | $"{anyObject2} hashcode is {anyObject2.GetHashCode()}"); 8 | 9 | var point1 = new Point(10, 20); 10 | var point2 = new Point(10, 20); 11 | var point3 = new Point(20, 30); 12 | Console.WriteLine($"{point1} hash code is {point1.GetHashCode()}"); 13 | Console.WriteLine($"{point2} hash code is {point2.GetHashCode()}"); 14 | Console.WriteLine($"{point3} hash code is {point3.GetHashCode()}"); 15 | 16 | Console.ReadKey(); 17 | 18 | class Point 19 | { 20 | public int X { get; } 21 | public int Y { get; } 22 | public Point(int x, int y) 23 | { 24 | X = x; 25 | Y = y; 26 | } 27 | 28 | public override int GetHashCode() 29 | { 30 | return HashCode.Combine(X, Y); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return $"X={X}, Y={Y}"; 36 | } 37 | } 38 | 39 | class Person 40 | { 41 | public string FirstName { get; } 42 | public string LastName { get; } 43 | public int YearOfBirth { get; } 44 | 45 | public override int GetHashCode() 46 | { 47 | return HashCode.Combine(FirstName, LastName, YearOfBirth); 48 | } 49 | 50 | public Person(string firstName, string lastName, int yearOfBirth) 51 | { 52 | FirstName = firstName; 53 | LastName = lastName; 54 | YearOfBirth = yearOfBirth; 55 | } 56 | } -------------------------------------------------------------------------------- /InversionOfControl_WinFormsApp/HelloForm.cs: -------------------------------------------------------------------------------- 1 | namespace InversionOfControl_WinFormsApp 2 | { 3 | public partial class HelloForm : Form 4 | { 5 | public HelloForm() 6 | { 7 | InitializeComponent(); 8 | } 9 | 10 | private void YearOfBirthTextBox_KeyPress(object sender, KeyPressEventArgs e) 11 | { 12 | e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar); 13 | YearOfBirthTextBox.BackColor = Color.White; 14 | } 15 | 16 | private void SubmitButton_Click(object sender, EventArgs e) 17 | { 18 | SetBackColor(NameTextBox); 19 | SetBackColor(YearOfBirthTextBox); 20 | 21 | if(!string.IsNullOrEmpty(NameTextBox.Text) && 22 | !string.IsNullOrEmpty(YearOfBirthTextBox.Text)) 23 | { 24 | int age = DateTime.Now.Year - int.Parse( 25 | YearOfBirthTextBox.Text); 26 | ResultTextBox.Text = $"Hello {NameTextBox.Text}! You are " + 27 | $"{age} years old!"; 28 | } 29 | } 30 | 31 | private void SetBackColor(TextBox textBox) 32 | { 33 | if (string.IsNullOrEmpty(textBox.Text)) 34 | { 35 | textBox.BackColor = Color.IndianRed; 36 | } 37 | else 38 | { 39 | textBox.BackColor = Color.White; 40 | } 41 | } 42 | 43 | private void NameTextBox_KeyPress(object sender, KeyPressEventArgs e) 44 | { 45 | NameTextBox.BackColor = Color.White; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /FuncsAndLambdaExpressions/Program.cs: -------------------------------------------------------------------------------- 1 | var numbers = new[] { 1, 3, 6, 1, 12 }; 2 | 3 | Console.WriteLine( 4 | "IsAnyLargerThan10? " + IsAny(numbers, IsLargerThan10)); 5 | 6 | Console.WriteLine( 7 | "IsAnyEven? " + IsAny(numbers, IsEven)); 8 | 9 | //the same result, but with lambda expressions 10 | Console.WriteLine( 11 | "IsAnyLargerThan10? " + IsAny(numbers, n => n > 10)); 12 | 13 | Console.WriteLine( 14 | "IsAnyEven? " + IsAny(numbers, n => n % 2 == 0)); 15 | 16 | 17 | //this function takes int, DateTime and string and resturns a bool 18 | Func someFunc; 19 | 20 | //this function takes two strings and a bool and is void 21 | 22 | Action someAction; 23 | 24 | Console.ReadKey(); 25 | 26 | bool IsAny( 27 | IEnumerable numbers, 28 | Func predicate) 29 | { 30 | foreach (var number in numbers) 31 | { 32 | if (predicate(number)) 33 | { 34 | return true; 35 | } 36 | } 37 | return false; 38 | } 39 | 40 | bool IsAnyLargerThan10(IEnumerable numbers) 41 | { 42 | foreach (var number in numbers) 43 | { 44 | if (number > 10) 45 | { 46 | return true; 47 | } 48 | } 49 | return false; 50 | } 51 | 52 | bool IsAnyEven(IEnumerable numbers) 53 | { 54 | foreach (var number in numbers) 55 | { 56 | if (number % 2 == 0) 57 | { 58 | return true; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | bool IsLargerThan10(int number) 65 | { 66 | return number > 10; 67 | } 68 | 69 | bool IsEven(int number) 70 | { 71 | return number % 2 == 0; 72 | } -------------------------------------------------------------------------------- /TemplateMethod_UnitTests/Program.cs: -------------------------------------------------------------------------------- 1 | var calculatorTests = new CalculatorTests(); 2 | Console.WriteLine(calculatorTests.Run() ? "Success!" : "Failure"); 3 | Console.ReadKey(); 4 | 5 | abstract class TestFixture 6 | { 7 | public bool Run() 8 | { 9 | int failedTestsCount = 0; 10 | foreach (var test in GetTests()) 11 | { 12 | SetUp(); 13 | if (!test()) 14 | { 15 | failedTestsCount++; 16 | } 17 | TearDown(); 18 | } 19 | return failedTestsCount == 0; 20 | } 21 | 22 | protected abstract IEnumerable> GetTests(); 23 | protected abstract void SetUp(); 24 | protected abstract void TearDown(); 25 | } 26 | 27 | class Calculator 28 | { 29 | public int Add(int a, int b) 30 | { 31 | return a + b; 32 | } 33 | } 34 | 35 | class CalculatorTests : TestFixture 36 | { 37 | private Calculator _cut; 38 | 39 | protected override void SetUp() 40 | { 41 | _cut = new Calculator(); 42 | Console.WriteLine("SetUp of MyTests class"); 43 | } 44 | 45 | protected override IEnumerable> GetTests() 46 | { 47 | return new List>() 48 | { 49 | () => 50 | { 51 | Console.WriteLine("3 + 2 shall be 5"); 52 | return _cut.Add(3,2) == 5; 53 | }, 54 | () => 55 | { 56 | Console.WriteLine("10 + (-10) shall be 0"); 57 | return _cut.Add(10, -10) == 0; 58 | } 59 | }; 60 | } 61 | 62 | protected override void TearDown() 63 | { 64 | Console.WriteLine("TearDown of MyTests class"); 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /ThrowVsThrowEx/Program.cs: -------------------------------------------------------------------------------- 1 | //MethodA(); 2 | 3 | try 4 | { 5 | MethodThrow(); 6 | } 7 | catch (Exception ex) 8 | { 9 | Console.WriteLine("Throw"); 10 | Console.WriteLine( 11 | "Exception caught, logging some" + 12 | " information. Stack trace:\n"); 13 | Console.WriteLine(ex.StackTrace); 14 | Console.WriteLine(); 15 | } 16 | 17 | try 18 | { 19 | MethodThrowEx(); 20 | } 21 | catch (Exception ex) 22 | { 23 | Console.WriteLine("Throw ex"); 24 | Console.WriteLine("Exception caught, logging some" + 25 | " information. Stack trace:\n"); 26 | Console.WriteLine(ex.StackTrace); 27 | Console.WriteLine(); 28 | } 29 | 30 | Console.ReadKey(); 31 | 32 | void MethodThrow() 33 | { 34 | try 35 | { 36 | var collection = Enumerable.Empty(); 37 | var first = collection.First(); 38 | } 39 | catch (Exception ex) 40 | { 41 | throw; 42 | } 43 | } 44 | 45 | void MethodThrowEx() 46 | { 47 | try 48 | { 49 | var collection = Enumerable.Empty(); 50 | var first = collection.First(); 51 | } 52 | catch (Exception ex) 53 | { 54 | throw ex; 55 | } 56 | } 57 | 58 | static void MethodA() 59 | { 60 | Console.WriteLine("In method A"); 61 | MethodB(); 62 | } 63 | 64 | static void MethodB() 65 | { 66 | Console.WriteLine("In method B"); 67 | MethodC(); 68 | } 69 | 70 | static void MethodC() 71 | { 72 | Console.WriteLine("In method C"); 73 | Console.WriteLine(Environment.StackTrace); 74 | Console.WriteLine(); 75 | } 76 | 77 | decimal Divide(decimal a, decimal b) 78 | { 79 | if(b == 0) 80 | { 81 | throw new ArgumentException("B can't be zero!"); 82 | } 83 | return a / b; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /Indexers/Program.cs: -------------------------------------------------------------------------------- 1 | var numbers = new int[] { 10, 20, 30 }; 2 | var atIndex1 = numbers[1]; //indexer of an array 3 | 4 | var list = new List { 5.5m, 3m, 0m }; 5 | var thirdElement = list[2]; 6 | 7 | var text = "hello"; 8 | var secondLetter = text[1]; //indexer of a string 9 | 10 | var currencies = new Dictionary 11 | { 12 | ["USA"] = "USD", 13 | ["Great Britain"] = "GBP", 14 | ["Poland"] = "PLN" 15 | }; 16 | var currencyInGreatBritain = currencies["Great Britain"]; //indexer of a Dictionary 17 | 18 | //custom indexers, defined for our own type 19 | var myList = new MyList(numbers); 20 | var secondValue = myList[1]; 21 | var firstValue = myList["0"]; 22 | var thirdValue = myList[1, 1]; //value at index 1+1 will be retrieved 23 | //this indexer is readonly, so we can't update the value 24 | //myList[1, 1] = 5; 25 | 26 | Console.ReadKey(); 27 | 28 | class MyList 29 | { 30 | private T[] _numbers; 31 | 32 | public MyList(T[] numbers) 33 | { 34 | _numbers = numbers; 35 | } 36 | 37 | //this is correct, but much longer than expression-bodied indexer defined below 38 | //public T this[int index] 39 | //{ 40 | // get 41 | // { 42 | // return _numbers[index]; 43 | // } 44 | // set 45 | // { 46 | // _numbers[index] = value; 47 | // } 48 | //} 49 | 50 | public T this[int index] 51 | { 52 | get => _numbers[index]; 53 | set => _numbers[index] = value; 54 | } 55 | 56 | public T this[string textIndex] 57 | { 58 | get => _numbers[int.Parse(textIndex)]; 59 | set => _numbers[int.Parse(textIndex)] = value; 60 | } 61 | 62 | public T this[int index1, int index2] 63 | { 64 | get => _numbers[index1 + index2]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CollectionsLists/Program.cs: -------------------------------------------------------------------------------- 1 | var list = new List { 1,2,3 }; 2 | list.Add(4); 3 | list[0] = 5; 4 | var last = list[list.Count - 1]; 5 | 6 | //List provided many useful methods 7 | list.RemoveAt(0); //removes element at given index 8 | list.Clear(); //empties the List 9 | list.AddRange(new []{ 5, 6, 7 }); //adds multiple elements 10 | bool contains7 = list.Contains(7); //checks if contains a value 11 | list.Prepend(10); //adds element at the beginning of the :ist 12 | list.Sort(); //sorts the List 13 | 14 | var newList = new List(); 15 | Console.WriteLine( 16 | $"Newly created list capacity: {newList.Capacity}"); 17 | 18 | newList.Add(5); 19 | Console.WriteLine( 20 | $"Capacity after adding 1 item: {newList.Capacity}"); 21 | 22 | newList.AddRange(new [] {6,7,8,9}); 23 | Console.WriteLine( 24 | $"Capacity when 5 items inside: {newList.Capacity}"); 25 | 26 | newList.Clear(); 27 | Console.WriteLine( 28 | $"Capacity after clearing: {newList.Capacity}"); 29 | 30 | var listOfCapacity1050 = new List(1050); 31 | Console.WriteLine( 32 | $"Capacity set to: {listOfCapacity1050.Capacity}"); 33 | 34 | listOfCapacity1050.AddRange(Enumerable.Range(0, 2000)); 35 | Console.WriteLine( 36 | $"Capacity is now: {listOfCapacity1050.Capacity}"); 37 | 38 | var listOfCapacity1000 = new List(1000); 39 | listOfCapacity1000.Add(5); 40 | listOfCapacity1000.TrimExcess(); //sets the Capacity to the actual count of items 41 | Console.WriteLine( 42 | $"Capacity after TrimExcess: {listOfCapacity1000.Capacity}"); 43 | 44 | var listOfSize4 = new List { 1, 2, 3, 4 }; 45 | //the below will throw an exception, because 46 | //Capacity can't be smaller than actual size 47 | //listOfSize4.Capacity = 1; 48 | 49 | //inserting the elements is an O(N) operation 50 | var someList = new List { 1, 2, 3, 5, 6 }; 51 | someList.Insert(3, 4); 52 | 53 | Console.ReadKey(); 54 | -------------------------------------------------------------------------------- /OperatorOverloading/Program.cs: -------------------------------------------------------------------------------- 1 | var point1 = new Point(10, 5); 2 | var point2 = new Point(-3, 4); 3 | var result = point1 + point2; 4 | //Console.WriteLine(point1.Add(point2)); 5 | Console.WriteLine(point1 + point2); 6 | 7 | //implicit conversion 8 | int a = 5; 9 | double b = a; 10 | 11 | //implicit conversion won't work here because we will lose precision 12 | double c = 5.5d; 13 | //int d = c; 14 | 15 | //we must use explicit conversion 16 | int d = (int)c; 17 | 18 | Point fromTuple = (Point)(5, 7); 19 | 20 | Console.ReadKey(); 21 | 22 | static void ReceiveExternalPoint((float, float) externalPoint) 23 | { 24 | //Point point = new Point(externalPoint.Item1, externalPoint.Item2); 25 | Point point = externalPoint; 26 | Console.WriteLine($"{point} received"); 27 | 28 | //this doesn't work, I can't use implicit cast from double to int 29 | //int a = 10.1; 30 | int a = (int)10; 31 | double b = 10; 32 | } 33 | 34 | static void ReceiveExternalPointDouble((double, double) externalPoint) 35 | { 36 | Point point = (Point)externalPoint; 37 | Console.WriteLine($"{point} received"); 38 | } 39 | 40 | record struct Point 41 | { 42 | public float X { get; } 43 | public float Y { get; } 44 | 45 | public Point(float x, float y) 46 | { 47 | X = x; 48 | Y = y; 49 | } 50 | 51 | public Point Add(Point other) 52 | { 53 | return new Point(X + other.X, Y + other.Y); 54 | } 55 | 56 | public static Point operator +(Point point1, Point point2) => 57 | new Point(point1.X + point1.X, point1.Y + point2.Y); 58 | 59 | public static implicit operator Point((float, float) externalPoint) => 60 | new Point(externalPoint.Item1, externalPoint.Item2); 61 | 62 | public static explicit operator Point((double, double) externalPoint) => 63 | new Point((float)externalPoint.Item1, (float)externalPoint.Item2); 64 | } -------------------------------------------------------------------------------- /StringImmutability/Program.cs: -------------------------------------------------------------------------------- 1 | //value type bahavior - they are passed by value 2 | var valueType = 5; 3 | Console.WriteLine($"Value type is {valueType}"); 4 | Console.WriteLine("Executing AddOneToValueType method"); 5 | AddOneToValueType(valueType); 6 | Console.WriteLine($"Now value type is {valueType}"); 7 | 8 | Console.WriteLine(); 9 | 10 | //reference type bahavior - they are passed by reference 11 | var referenceType = new List { 5 }; 12 | Console.WriteLine($"Reference type has {referenceType.Count} elements"); 13 | Console.WriteLine("Executing AddOneToReferenceType method"); 14 | AddOneToReferenceType(referenceType); 15 | Console.WriteLine($"Now reference type has {referenceType.Count} elements"); 16 | 17 | Console.WriteLine(); 18 | 19 | //string behavior 20 | var text = "Hello!"; 21 | Console.WriteLine($"text is {text}"); 22 | Console.WriteLine("Executing AddOneToString method"); 23 | AddOneToString(text); 24 | Console.WriteLine($"Now text is {text}"); 25 | 26 | Console.WriteLine(); 27 | 28 | List list1 = new List { 1, 2, 3 }; 29 | List list2 = new List { 1, 2, 3 }; 30 | Console.WriteLine( 31 | $"Are two reference type objects equal " + 32 | $"by value considered equal?: {list1 == list2}"); 33 | 34 | var string1 = "abc"; 35 | var string2 = "abc"; 36 | Console.WriteLine( 37 | $"Are two string objects equal " + 38 | $"by value considered equal?: {string1 == string2}"); 39 | 40 | //Interning 41 | //if many variables point to the same strings 42 | //the runtime actually holds only one copy of it in the memory 43 | var text1 = "Hello!"; 44 | var text2 = "Hello!"; 45 | var text3 = "Hello!"; 46 | var text4 = "Hello!"; 47 | 48 | Console.ReadKey(); 49 | 50 | 51 | void AddOneToValueType(int valueType) 52 | { 53 | ++valueType; 54 | } 55 | 56 | void AddOneToReferenceType(List referenceType) 57 | { 58 | referenceType.Add(6); 59 | } 60 | 61 | void AddOneToString(string text) 62 | { 63 | text += "1"; 64 | } -------------------------------------------------------------------------------- /CollectionsDictionary/Program.cs: -------------------------------------------------------------------------------- 1 | var currencies = new Dictionary(); 2 | currencies["USA"] = "USD"; 3 | currencies["Japan"] = "JPY"; 4 | currencies["Brazil"] = "BRL"; 5 | 6 | var currenciesValuesComparedToDollar = new Dictionary(); 7 | currenciesValuesComparedToDollar.Add("USD", 1m); 8 | currenciesValuesComparedToDollar.Add("JPY", 0.0086m); 9 | currenciesValuesComparedToDollar.Add("BRL", 0.18m); 10 | //Dictionary keys must be unique, so the below line will throw an exception 11 | //currenciesValuesComparedToDollar.Add("BRL", 0.18m); 12 | 13 | currenciesValuesComparedToDollar["BRL"] = 0.19m; //this will update the value 14 | 15 | var savedGames = new Dictionary 16 | { 17 | ["save1"] = @"C:/saves/save1.dat", 18 | ["autosave"] = @"C:/saves/auto/save.dat", 19 | ["beforeBossFight"] = @"C:/saves/beforeBossFight.dat", 20 | }; 21 | 22 | var employees = new List 23 | { 24 | new Employee(Department.Xenobiology, 15000), 25 | new Employee(Department.MissionControl, 10000), 26 | new Employee(Department.PlanetTerraforming, 9000), 27 | new Employee(Department.PlanetTerraforming, 8000), 28 | new Employee(Department.MissionControl, 11000), 29 | new Employee(Department.MissionControl, 12000), 30 | }; 31 | 32 | //let's build a mapping from the department to the average 33 | //salary in this department 34 | Dictionary departmentsAverageSalaries = 35 | employees 36 | .GroupBy(e => e.Department) 37 | .ToDictionary( 38 | grouping => grouping.Key, 39 | grouping => grouping.Average(g => g.Salary)); 40 | 41 | foreach (var departmentsAverageSalary in departmentsAverageSalaries) 42 | { 43 | Console.WriteLine($"{departmentsAverageSalary.Key}: {departmentsAverageSalary.Value}"); 44 | } 45 | 46 | Console.ReadKey(); 47 | 48 | record Employee(Department Department, decimal Salary); 49 | enum Department { MissionControl, Xenobiology, PlanetTerraforming } -------------------------------------------------------------------------------- /ExpressionBodiedMembers/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | Console.ReadKey(); 3 | 4 | public class Person 5 | { 6 | public string Name { get; } 7 | public int YearOfBirth { get; } 8 | 9 | public Person(string name, int yearOfBirth) 10 | { 11 | Name = name; 12 | YearOfBirth = yearOfBirth; 13 | } 14 | 15 | public Person(string name) => Name = name; 16 | 17 | ~Person() => Console.WriteLine("Destructing the Person object"); 18 | 19 | //this takes 7 lines 20 | //public int Age 21 | //{ 22 | // get 23 | // { 24 | // return DateTime.Now.Year - YearOfBirth; 25 | // } 26 | //} 27 | 28 | //and this takes 1! 29 | public int Age => DateTime.Now.Year - YearOfBirth; 30 | 31 | 32 | //old-fashioned property with extra operation on set 33 | private string _lastName; 34 | //public string LastName 35 | //{ 36 | // get 37 | // { 38 | // return _lastName; 39 | // } 40 | // set 41 | // { 42 | // _lastName = value.Trim(); 43 | // } 44 | //} 45 | 46 | //expression-bodied property with extra operation on set 47 | public string LastName 48 | { 49 | get => _lastName; 50 | set => _lastName = value.Trim(); 51 | } 52 | 53 | public override string ToString() => $"{Name} who was born on {YearOfBirth}"; 54 | 55 | public void Print() => Console.WriteLine(ToString()); 56 | 57 | //we can;t make this method an expression-bodied method, because it has more 58 | //than one statement or expression 59 | public bool IsNameValid() 60 | { 61 | if (Name == null) 62 | { 63 | Console.WriteLine("Name is null."); 64 | return false; 65 | } 66 | if (Name.Length == 0) 67 | { 68 | Console.WriteLine("Name is too short."); 69 | return false; 70 | } 71 | if (Name.Length > 25) 72 | { 73 | Console.WriteLine("Name is too long."); 74 | return false; 75 | } 76 | return true; 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /InversionOfControl/Program.cs: -------------------------------------------------------------------------------- 1 | var input = @"Said the Duck, ‘As I sate on the rocks, 2 | I have thought over that completely, 3 | And I bought four pairs of worsted socks 4 | Which fit my web-feet neatly. 5 | And to keep out the cold I’ve bought a cloak, 6 | And every day a cigar I’ll smoke, 7 | All to follow my own dear true 8 | Love of a Kangaroo!"; 9 | 10 | ReadLineByLine(input, () => Console.WriteLine("Finished!")); 11 | Console.ReadKey(); 12 | 13 | void ReadLineByLine(string input, Action onFinished) 14 | { 15 | string[] lines = input.Split(Environment.NewLine); 16 | for (int i = 0; i < lines.Length; i++) 17 | { 18 | string line = lines[i]; 19 | Console.WriteLine($"[Line number {i}] {line}"); 20 | } 21 | onFinished(); 22 | } 23 | 24 | //Interfaces and callbacks (Funcs, Actions) have much in common 25 | //Func or action is like an interface with single method 26 | class PersonalDataFormatterWithInterface 27 | { 28 | private readonly IPeopleDataReader _peopleDataReader; 29 | 30 | public PersonalDataFormatterWithInterface(IPeopleDataReader peopleDataReader) 31 | { 32 | _peopleDataReader = peopleDataReader; 33 | } 34 | 35 | public string Format() 36 | { 37 | var people = _peopleDataReader.ReadPeople(); 38 | return string.Join("\n", 39 | people.Select(p => $"{p.Name} born in" + 40 | $" {p.Country} on {p.YearOfBirth}")); 41 | } 42 | } 43 | 44 | class PersonalDataFormatterWithFunc 45 | { 46 | private readonly Func> _getPeople; 47 | 48 | public PersonalDataFormatterWithFunc(Func> getPeople) 49 | { 50 | _getPeople = getPeople; 51 | } 52 | 53 | public string Format() 54 | { 55 | var people = _getPeople(); 56 | return string.Join("\n", 57 | people.Select(p => $"{p.Name} born in" + 58 | $" {p.Country} on {p.YearOfBirth}")); 59 | } 60 | } 61 | 62 | interface IPeopleDataReader 63 | { 64 | IEnumerable ReadPeople(); 65 | } 66 | 67 | record Person(string Name, int YearOfBirth, string Country); -------------------------------------------------------------------------------- /IsVsAs/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | //"is" keyword checks if object is of given type 3 | //it returns a boolean result 4 | object text = "Hello!"; 5 | //"as" can be only used to cast to reference types of Nullable 6 | //int textAsInt = text as int; 7 | 8 | bool isString = text is string; 9 | Console.WriteLine("isString? " + isString); 10 | 11 | //we can use "is" to check if an object is a reference type or a value type 12 | bool isInt = text is int; 13 | Console.WriteLine("isInt? " + isInt); 14 | 15 | //"as" is used to cast an object to a given type 16 | string textAsString = text as string; 17 | 18 | Console.WriteLine(textAsString + " -> it's now a string"); 19 | 20 | //"as" doesn't work with value types 21 | //that's why below line doesn't compile 22 | //long longNumber = number as long; 23 | 24 | //the only expection is nullable 25 | //it is a value type, but we can use "as" with it 26 | int number = 10; 27 | int? nullableNumber = number as int?; 28 | Console.WriteLine(nullableNumber + " -> it's now a nullable int"); 29 | 30 | int? nullAsNullableInt = null as int?; 31 | Console.WriteLine(nullAsNullableInt + " -> it's null"); 32 | 33 | //the reason why casting with "as" must be to reference types or nullable 34 | //is that if the casting will not succeed, the result will be null 35 | 36 | //This is the main difference between casting with "as" and regular casting 37 | //is that when casting with "as" fails, it will give null 38 | //whereas if regular casting will fail, it will throw an exception 39 | 40 | object numbers = new int[] { 1, 2, 3 }; 41 | 42 | //the below will succeed and will give a non-null value 43 | var asIList = numbers as IList; 44 | Console.WriteLine("asIList is null? : " + (asIList == null)); 45 | var castToIList = (IList)numbers; 46 | 47 | //the below will not succeed and will give a null value 48 | var asList = numbers as List; 49 | Console.WriteLine("asList is null? : " + (asList == null)); 50 | 51 | //the below will not succeed and will throw an exception 52 | try 53 | { 54 | var castToList = (List)numbers; 55 | } 56 | catch (InvalidCastException) 57 | { 58 | Console.WriteLine("InvalidCastException has been thrown"); 59 | } 60 | 61 | Console.ReadKey(); -------------------------------------------------------------------------------- /CheckedPerformanceTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | const int setSize = 1000000000; 4 | var checkedResult = MeasureChecked(setSize); 5 | Console.WriteLine($"Checked test for {setSize} took {checkedResult} ms"); 6 | 7 | GC.Collect(); 8 | var uncheckedResult = MeasureUnchecked(setSize); 9 | Console.WriteLine($"Unchecked test for {setSize} took {uncheckedResult} ms"); 10 | Console.WriteLine($"Checked took {(((double)checkedResult / (double)uncheckedResult) - 1d) * 100}% longer"); 11 | 12 | GC.Collect(); 13 | var uncheckedWithManualCheckResult = MeasureUncheckedWithManualCheck(setSize); 14 | Console.WriteLine($"Unchecked with manual check test for {setSize} took {uncheckedWithManualCheckResult} ms"); 15 | 16 | Console.ReadLine(); 17 | 18 | static long MeasureChecked(int setSize) 19 | { 20 | var stopwatch = Stopwatch.StartNew(); 21 | 22 | int a = 1; 23 | int b = 2; 24 | 25 | checked 26 | { 27 | for (int i = 0; i < setSize; i++) 28 | { 29 | a = i + b + a; 30 | a = 1; 31 | } 32 | } 33 | 34 | stopwatch.Stop(); 35 | return stopwatch.ElapsedMilliseconds; 36 | } 37 | 38 | static long MeasureUnchecked(int setSize) 39 | { 40 | var stopwatch = Stopwatch.StartNew(); 41 | 42 | int a = 1; 43 | int b = 2; 44 | 45 | unchecked 46 | { 47 | for (int i = 0; i < setSize; i++) 48 | { 49 | a = i + b + a; 50 | a = 1; 51 | } 52 | } 53 | 54 | stopwatch.Stop(); 55 | return stopwatch.ElapsedMilliseconds; 56 | } 57 | 58 | static long MeasureUncheckedWithManualCheck(int setSize) 59 | { 60 | var stopwatch = Stopwatch.StartNew(); 61 | 62 | int a = 1; 63 | int b = 2; 64 | 65 | unchecked 66 | { 67 | for (int i = 0; i < setSize; i++) 68 | { 69 | if (((long)i + (long)b + (long)a) > int.MaxValue) 70 | { 71 | throw new InvalidOperationException( 72 | "The operation will result in int overflow"); 73 | } 74 | a = i + b + a; 75 | a = 1; 76 | } 77 | } 78 | 79 | stopwatch.Stop(); 80 | return stopwatch.ElapsedMilliseconds; 81 | } 82 | 83 | 84 | -------------------------------------------------------------------------------- /PatternMatching/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine(TypeCheck("some string")); 2 | Console.WriteLine(Properties("not a pet")); 3 | Console.WriteLine(Properties(new Pet("Bobby", PetType.Fish, 136000))); 4 | Console.WriteLine(Properties(new Pet("Taiga", PetType.Dog, 30))); 5 | 6 | Console.ReadKey(); 7 | 8 | //null check 9 | string NullCheck(object obj) 10 | { 11 | if (obj is null) 12 | { 13 | return "Object is null!"; 14 | } 15 | else 16 | { 17 | return "Object is null not null: " + obj.ToString(); 18 | } 19 | } 20 | 21 | //type check 22 | string TypeCheck(object obj) 23 | { 24 | if (obj is string asString) 25 | { 26 | return "String is: " + asString; 27 | } 28 | else 29 | { 30 | return "Obj is not a string"; 31 | } 32 | } 33 | 34 | object ComparingDiscreteValues(string number, string type) 35 | { 36 | return type switch 37 | { 38 | "int" => int.Parse(number), 39 | "decimal" => decimal.Parse(number), 40 | "float" => float.Parse(number), 41 | _ => throw new ArgumentException($"{type} type is not supported"), 42 | }; 43 | } 44 | 45 | string Relational(int age) 46 | { 47 | return age switch 48 | { 49 | 18 => "just become adult, at least in some countries", 50 | (> 20) and (< 60) => "middle-aged", 51 | < 11 => "child", 52 | < 20 => "teenager", 53 | > 60 => "senior", 54 | }; 55 | } 56 | 57 | string Properties(object obj) 58 | { 59 | if (obj is Pet { Weight: > 10000, TypeOfPet: PetType.Fish }) 60 | { 61 | return "It must be a whale shark!"; 62 | } 63 | if(obj is Pet) 64 | { 65 | return "It's some kind of pet."; 66 | } 67 | return "It's definitely not a pet."; 68 | } 69 | 70 | string Deconstruction(Pet pet) 71 | { 72 | return pet switch 73 | { 74 | (_, TypeOfPet: PetType.Dog, Weight: 10) => "Small dog of any name", 75 | (Name: "Hannibal", TypeOfPet: PetType.Fish, _) => "Fish called Hannibal", 76 | Pet { Weight: >100 } => "Heavy pet", 77 | _ => "Unknown!" 78 | }; 79 | } 80 | 81 | public record Pet(string Name, PetType TypeOfPet, float Weight); 82 | public enum PetType { Cat, Dog, Fish } 83 | -------------------------------------------------------------------------------- /CompositionOverInheritance_Inheritance/Program.cs: -------------------------------------------------------------------------------- 1 | var factory = new PersonalDataFormatterFactory(); 2 | 3 | var fromExcel = factory.Create(Source.Excel); 4 | Console.WriteLine(fromExcel.Format()); 5 | 6 | Console.WriteLine(); 7 | 8 | var fromDatabase = factory.Create(Source.Database); 9 | Console.WriteLine(fromDatabase.Format()); 10 | 11 | Console.ReadKey(); 12 | 13 | enum Source { Database, Excel } 14 | 15 | class PersonalDataFormatterFactory 16 | { 17 | public PersonalDataFormatter Create(Source source) 18 | { 19 | switch (source) 20 | { 21 | case Source.Database: 22 | return new DatabaseSourcedPersonalDataFormatter(); 23 | case Source.Excel: 24 | return new ExcelSourcedPersonalDataFormatter(); 25 | default: 26 | throw new ArgumentException("Invalid source"); 27 | } 28 | } 29 | } 30 | 31 | abstract class PersonalDataFormatter 32 | { 33 | public string Format() 34 | { 35 | var people = ReadPeople(); 36 | return string.Join("\n", 37 | people.Select(p => $"{p.Name} born in" + 38 | $" {p.Country} on {p.YearOfBirth}")); 39 | } 40 | 41 | protected abstract IEnumerable ReadPeople(); 42 | } 43 | 44 | class DatabaseSourcedPersonalDataFormatter : PersonalDataFormatter 45 | { 46 | protected override IEnumerable ReadPeople() 47 | { 48 | Console.WriteLine("Reading from database"); 49 | return new List 50 | { 51 | new Person("John", 1982, "USA"), 52 | new Person("Aja", 1992, "India"), 53 | new Person("Tom", 1954, "Australia"), 54 | }; 55 | } 56 | } 57 | 58 | class ExcelSourcedPersonalDataFormatter : PersonalDataFormatter 59 | { 60 | protected override IEnumerable ReadPeople() 61 | { 62 | Console.WriteLine("Reading from an Excel file"); 63 | return new List 64 | { 65 | new Person("Martin", 1972, "France"), 66 | new Person("Aiko", 1995, "Japan"), 67 | new Person("Selene", 1944, "Great Britain"), 68 | }; 69 | } 70 | } 71 | 72 | record Person(string Name, int YearOfBirth, string Country); 73 | -------------------------------------------------------------------------------- /AnonymousTypes/Program.cs: -------------------------------------------------------------------------------- 1 | var person = new { Name = "Martin", City = "Savannah", Age = 45 }; 2 | 3 | Console.WriteLine($"This person's name is {person.Name}," + 4 | $"he lives in {person.City} and is {person.Age} years old"); 5 | 6 | //anonymous types properties are read-only 7 | //so this will not compile 8 | //person.Name = "Jack"; 9 | 10 | var pets = new[] 11 | { 12 | new Pet("Hannibal", PetType.Fish, 1.1f), 13 | new Pet("Anthony", PetType.Cat, 2f), 14 | new Pet("Ed", PetType.Cat, 0.7f), 15 | new Pet("Taiga", PetType.Dog, 35f), 16 | new Pet("Rex", PetType.Dog, 40f), 17 | new Pet("Lucky", PetType.Dog, 5f), 18 | new Pet("Storm", PetType.Cat, 0.9f), 19 | new Pet("Nyan", PetType.Cat, 2.2f) 20 | }; 21 | 22 | //we could use a regular type, but it most likely would not be used anywhere else 23 | //var averageWeightsData = pets 24 | // .GroupBy(pet => pet.PetType) 25 | // .Select(grouping => new PetTypeAverageWeightPair( 26 | // grouping.Key, 27 | // grouping.Average(pet => pet.Weight))) 28 | // .OrderBy(data => data.AverageWeight) 29 | // .Select(data => $"Average weight for type {data.Type} is {data.WeightAverage}"); 30 | 31 | var averageWeightsData = pets 32 | .GroupBy(pet => pet.PetType) 33 | .Select(grouping => new 34 | { 35 | Type = grouping.Key, 36 | WeightAverage = grouping.Average(pet => pet.Weight) 37 | }) 38 | .OrderBy(data => data.WeightAverage) 39 | .Select(data => $"Average weight for type " + 40 | $"{data.Type} is {data.WeightAverage}"); 41 | 42 | Console.WriteLine(string.Join(Environment.NewLine, averageWeightsData)); 43 | 44 | //anonymous types support non-destructive mutation 45 | var someData = new { number = 5, text = "hello!" }; 46 | var changedData = someData with { number = 10 }; 47 | 48 | var theSameData = new { number = 5, text = "hello!" }; 49 | Console.WriteLine("Are equal? " + someData.Equals(theSameData)); 50 | Console.WriteLine($"someData hashcode: {someData.GetHashCode()}, " + 51 | $"theSameData: {theSameData.GetHashCode()}"); 52 | Console.ReadKey(); 53 | 54 | record PetTypeAverageWeightPair( 55 | PetType PetType, float AverageWeight); 56 | 57 | public record Pet(string Name, PetType PetType, float Weight); 58 | public enum PetType { Cat, Dog, Fish } 59 | 60 | -------------------------------------------------------------------------------- /Caching/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Caching.Memory; 2 | 3 | var peopleController = new PeopleController( 4 | new PeopleRepositoryMock()); 5 | 6 | var john = peopleController.GetByName("John", "Smith"); 7 | john = peopleController.GetByName("John", "Smith"); 8 | john = peopleController.GetByName("John", "Smith"); 9 | 10 | Console.ReadKey(); 11 | 12 | class Cache where TKey: notnull 13 | { 14 | private readonly Dictionary _cachedData = new(); 15 | 16 | public TValue Get(TKey key, Func getValueForTheFirstTime) 17 | { 18 | if (!_cachedData.ContainsKey(key)) 19 | { 20 | _cachedData[key] = getValueForTheFirstTime(); 21 | } 22 | return _cachedData[key]; 23 | } 24 | } 25 | 26 | class PeopleController 27 | { 28 | private readonly Cache<(string, string), Person?> _cache = new(); 29 | private readonly IRepository _peopleRepository; 30 | 31 | public PeopleController(IRepository peopleRepository) 32 | { 33 | _peopleRepository = peopleRepository; 34 | } 35 | 36 | public Person? GetByName(string firstName, string lastName) 37 | { 38 | return _cache.Get( 39 | (firstName, lastName), 40 | () => _peopleRepository 41 | .GetByName(firstName, lastName) 42 | .FirstOrDefault()); 43 | } 44 | 45 | private readonly MemoryCache _memoryCache = 46 | new MemoryCache(new MemoryCacheOptions()); 47 | 48 | //alternatively we can use the Microsoft's MemotyCache 49 | public Person? GetByNameMemoryCache(string firstName, string lastName) 50 | { 51 | return _memoryCache.GetOrCreate( 52 | (firstName, lastName), 53 | cacheEntry => _peopleRepository 54 | .GetByName(firstName, lastName) 55 | .FirstOrDefault()); 56 | } 57 | } 58 | 59 | internal interface IRepository 60 | { 61 | IEnumerable GetByName(string firstName, string lastName); 62 | } 63 | 64 | record Person(string FirstName, string LastName); 65 | 66 | class PeopleRepositoryMock : IRepository 67 | { 68 | public IEnumerable GetByName(string firstName, string lastName) 69 | { 70 | if (firstName == "John" && lastName == "Smith") 71 | { 72 | return new[] { new Person("John", "Smith") }; 73 | } 74 | throw new NotImplementedException(); 75 | } 76 | } -------------------------------------------------------------------------------- /CompositionOverInheritance_Composition/Program.cs: -------------------------------------------------------------------------------- 1 | var factory = new PersonalDataFormatterFactory(); 2 | 3 | var fromExcel = factory.Create(Source.Excel); 4 | Console.WriteLine(fromExcel.Format()); 5 | 6 | Console.WriteLine(); 7 | 8 | var fromDatabase = factory.Create(Source.Database); 9 | Console.WriteLine(fromDatabase.Format()); 10 | 11 | Console.ReadKey(); 12 | 13 | enum Source { Database, Excel } 14 | 15 | class PersonalDataFormatterFactory 16 | { 17 | public PersonalDataFormatter Create(Source source) 18 | { 19 | switch (source) 20 | { 21 | case Source.Database: 22 | return new PersonalDataFormatter( 23 | new DatabasePeopleDataReader()); 24 | case Source.Excel: 25 | return new PersonalDataFormatter( 26 | new ExcelPeopleDataReader()); 27 | default: 28 | throw new ArgumentException("Invalid source"); 29 | } 30 | } 31 | } 32 | 33 | interface IPeopleDataReader 34 | { 35 | IEnumerable ReadPeople(); 36 | } 37 | 38 | class PersonalDataFormatter 39 | { 40 | private readonly IPeopleDataReader _peopleDataReader; 41 | 42 | public PersonalDataFormatter(IPeopleDataReader peopleDataReader) 43 | { 44 | _peopleDataReader = peopleDataReader; 45 | } 46 | 47 | public string Format() 48 | { 49 | var people = _peopleDataReader.ReadPeople(); 50 | return string.Join("\n", 51 | people.Select(p => $"{p.Name} born in" + 52 | $" {p.Country} on {p.YearOfBirth}")); 53 | } 54 | } 55 | 56 | class DatabasePeopleDataReader : IPeopleDataReader 57 | { 58 | public IEnumerable ReadPeople() 59 | { 60 | Console.WriteLine("Reading from database"); 61 | return new List 62 | { 63 | new Person("John", 1982, "USA"), 64 | new Person("Aja", 1992, "India"), 65 | new Person("Tom", 1954, "Australia"), 66 | }; 67 | } 68 | } 69 | 70 | class ExcelPeopleDataReader : IPeopleDataReader 71 | { 72 | public IEnumerable ReadPeople() 73 | { 74 | Console.WriteLine("Reading from an Excel file"); 75 | return new List 76 | { 77 | new Person("Martin", 1972, "France"), 78 | new Person("Aiko", 1995, "Japan"), 79 | new Person("Selene", 1944, "Great Britain"), 80 | }; 81 | } 82 | } 83 | 84 | record Person(string Name, int YearOfBirth, string Country); 85 | -------------------------------------------------------------------------------- /DefaultInterfaceImplementation/Program.cs: -------------------------------------------------------------------------------- 1 | CustomOrder orderConcreteType = new CustomOrder(); 2 | //we can't use the default implementation on the concrete type 3 | //orderConcreteType.DelayDeliveryByDays(1); 4 | 5 | //but we can use it via the interface 6 | IOrder order = new CustomOrder(); 7 | order.DelayDeliveryByDays(1); 8 | 9 | IOrder orderWithDelay = new CustomOrderWithDelay(); 10 | orderWithDelay.DelayDeliveryByDays(1); 11 | orderWithDelay.VirtualMethodFromInterface(); 12 | Console.ReadKey(); 13 | 14 | 15 | class CustomOrder : IOrder 16 | { 17 | public IEnumerable Items { get; } = new List(); 18 | 19 | public ICustomer Customer {get;} 20 | 21 | public void Place() 22 | { 23 | Console.WriteLine("Placing an order"); 24 | } 25 | } 26 | 27 | class CustomOrderWithDelay : IOrder 28 | { 29 | public IEnumerable Items { get; } = new List(); 30 | 31 | public ICustomer Customer { get; } 32 | 33 | public void Place() 34 | { 35 | Console.WriteLine("Placing an order"); 36 | } 37 | 38 | public void DelayDeliveryByDays(int days) 39 | { 40 | Console.WriteLine("DelayDeliveryByDays from CustomOrderWithDelay"); 41 | 42 | //we can't use the protected method from the base interface 43 | //in the class implementing the interface 44 | //var x = ProtectedMethod(); 45 | } 46 | 47 | //we can't override the virtual method from interface in the class 48 | //public override void VirtualMethodFromInterface() { } 49 | } 50 | 51 | public interface IOrder 52 | { 53 | public virtual void VirtualMethodFromInterface() 54 | { 55 | Console.WriteLine("IOrder interface"); 56 | } 57 | 58 | IEnumerable Items { get; } 59 | ICustomer Customer { get; } 60 | void Place(); 61 | void DelayDeliveryByDays(int days) 62 | { 63 | Console.WriteLine($"DelayDeliveryByDays from interface"); 64 | } 65 | 66 | protected int ProtectedMethod() => 0; 67 | } 68 | 69 | public interface ICancellableOrder : IOrder 70 | { 71 | void IOrder.VirtualMethodFromInterface() 72 | { 73 | Console.WriteLine("ICancellableOrder interface"); 74 | 75 | //we can use the protected method from the base interface here 76 | var x = ProtectedMethod(); 77 | } 78 | void Cancel(); 79 | } 80 | 81 | public interface IItem 82 | { 83 | string Name { get; } 84 | decimal Price { get; } 85 | } 86 | 87 | public interface ICustomer 88 | { 89 | string Name { get; } 90 | string Email { get; } 91 | } -------------------------------------------------------------------------------- /Serialization/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Xml; 3 | using System.Xml.Serialization; 4 | 5 | const string filePath = "personalData.xml"; 6 | if (File.Exists(filePath)) 7 | { 8 | using Stream reader = new FileStream(filePath, FileMode.Open); 9 | var xmlSerializer = new XmlSerializer(typeof(Person)); 10 | 11 | StreamReader stream = new StreamReader(reader, Encoding.UTF8); 12 | var person = (Person?)xmlSerializer.Deserialize( 13 | new XmlTextReader(stream)); 14 | 15 | //for JSON format we would use this: 16 | //Person recreatedPerson = JsonConvert.DeserializeObject(json); 17 | 18 | Console.WriteLine($"Personal data read from xml:\n{person}"); 19 | } 20 | else 21 | { 22 | var name = Read("name"); 23 | var lastName = Read("last name"); 24 | var residence = Read("place of residence"); 25 | var hobby = Read("hobby"); 26 | 27 | var person = new Person(name, lastName, residence, hobby); 28 | 29 | string xml = Serialize(person); 30 | Console.WriteLine( 31 | $"The person object serialized to XML is:\n{xml}"); 32 | 33 | SaveXmlToFile(filePath, xml); 34 | 35 | //for JSON format we would use this 36 | //string json = JsonConvert.SerializeObject(person, Formatting.Indented); 37 | } 38 | Console.ReadKey(); 39 | 40 | static string Read(string what) 41 | { 42 | Console.WriteLine($"Enter the {what}:"); 43 | return Console.ReadLine(); 44 | } 45 | 46 | static string Serialize(Person person) 47 | { 48 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person)); 49 | 50 | var stringWriter = new StringWriter(); 51 | 52 | var xmlWriter = XmlWriter.Create( 53 | stringWriter, new XmlWriterSettings { Indent = true }); 54 | 55 | xmlSerializer.Serialize(xmlWriter, person); 56 | return stringWriter.ToString(); 57 | } 58 | 59 | static void SaveXmlToFile(string path, string xml) 60 | { 61 | File.WriteAllText(path, xml); 62 | } 63 | 64 | //the Serializable attribute is not needed for XML or JSON serialization 65 | //only for BinaryFormatter and SoapFormatter 66 | //[Serializable] 67 | public record Person 68 | { 69 | public string Name { get; set; } 70 | public string LastName { get; set; } 71 | public string Residence { get; set; } 72 | public string Hobby { get; set; } 73 | 74 | private Person() 75 | { 76 | 77 | } 78 | 79 | public Person(string name, string lastName, string residence, string hobby) 80 | { 81 | Name = name; 82 | LastName = lastName; 83 | Residence = residence; 84 | Hobby = hobby; 85 | } 86 | } -------------------------------------------------------------------------------- /Attributes/Program.cs: -------------------------------------------------------------------------------- 1 | //we can access type's metadata using reflection 2 | var type = typeof(Person); 3 | 4 | var validPerson = new Person("John", 1982); 5 | var invalidDog = new Dog("R"); 6 | var validator = new Validator(); 7 | 8 | Console.WriteLine(validator.Validate(validPerson) ? 9 | "Person is valid" : 10 | "Person is not valid"); 11 | Console.WriteLine(); 12 | Console.WriteLine(validator.Validate(invalidDog) ? 13 | "Dog is valid" : 14 | "Dog is not valid"); 15 | 16 | Console.ReadKey(); 17 | 18 | public class Dog 19 | { 20 | [StringLengthValidate(2, 10)] 21 | public string Name { get; } 22 | public Dog(string name) => Name = name; 23 | } 24 | 25 | public class Person 26 | { 27 | [StringLengthValidate(2, 25)] 28 | public string Name { get; } 29 | public int YearOfBirth { get; } 30 | 31 | public Person(string name, int yearOfBirth) 32 | { 33 | Name = name; 34 | YearOfBirth = yearOfBirth; 35 | } 36 | 37 | public Person(string name) => Name = name; 38 | } 39 | 40 | [AttributeUsage(AttributeTargets.Property)] 41 | class StringLengthValidateAttribute : Attribute 42 | { 43 | public int Min { get; } 44 | public int Max { get; } 45 | 46 | public StringLengthValidateAttribute(int min, int max) 47 | { 48 | Min = min; 49 | Max = max; 50 | } 51 | } 52 | 53 | class Validator 54 | { 55 | public bool Validate(object obj) 56 | { 57 | var type = obj.GetType(); 58 | var propertiesToValidate = type 59 | .GetProperties() 60 | .Where(property => 61 | Attribute.IsDefined( 62 | property, typeof(StringLengthValidateAttribute))); 63 | 64 | foreach (var property in propertiesToValidate) 65 | { 66 | var attribute = (StringLengthValidateAttribute) 67 | property.GetCustomAttributes( 68 | typeof(StringLengthValidateAttribute), true).First(); 69 | object? propertyValue = property.GetValue(obj); 70 | if(propertyValue is not string) 71 | { 72 | throw new InvalidOperationException( 73 | $"Attribute {nameof(StringLengthValidateAttribute)} " + 74 | $"can only be applied to strings."); 75 | } 76 | var value = (string)propertyValue; 77 | if (value.Length < attribute.Min || value.Length > attribute.Max) 78 | { 79 | Console.WriteLine($"Property {property.Name} is invalid. " + 80 | $"Value: {value}. The length must be between " + 81 | $"{attribute.Min} and {attribute.Max}"); 82 | return false; 83 | } 84 | } 85 | return true; 86 | } 87 | } -------------------------------------------------------------------------------- /CheckedKeyword/Program.cs: -------------------------------------------------------------------------------- 1 | int twoBillion = 2000000000; 2 | var result = twoBillion + twoBillion; 3 | 4 | Console.WriteLine("two billion + two billion is " + result); 5 | 6 | //the below code will thrown an exception, 7 | //because on overflow will happen in the checked scope 8 | //byte maxValueForByte = byte.MaxValue; 9 | //checked 10 | //{ 11 | // //this will throw an exception 12 | // maxValueForByte++; 13 | //} 14 | 15 | var account1 = new Account(); 16 | account1.MakePaymentNotChecked(1900000000); 17 | account1.MakePaymentNotChecked(1000000000); 18 | 19 | var account2 = new Account(); 20 | account2.MakePaymentChecked(1900000000); 21 | account2.MakePaymentChecked(1000000000); 22 | 23 | int Add(int a, int b) 24 | { 25 | return a + b; 26 | } 27 | 28 | void SomeMethodWithCheckedScopeInside() 29 | { 30 | try 31 | { 32 | checked 33 | { 34 | int i = Add(twoBillion, twoBillion); 35 | } 36 | } 37 | catch(OverflowException) 38 | { 39 | Console.WriteLine("Exception!"); 40 | } 41 | Console.WriteLine("SomeMethodWithCheckedScopeInside is finished"); 42 | } 43 | 44 | SomeMethodWithCheckedScopeInside(); 45 | Console.ReadKey(); 46 | 47 | public class Account 48 | { 49 | private int _todaysPaymentsSum; 50 | private const int MaxDailyPaymentsSum = 2000000000; 51 | 52 | public void MakePaymentChecked(int amount) 53 | { 54 | checked 55 | { 56 | try 57 | { 58 | var paymentsSumAfterPayment = _todaysPaymentsSum + amount; 59 | if (paymentsSumAfterPayment < MaxDailyPaymentsSum) 60 | { 61 | _todaysPaymentsSum = paymentsSumAfterPayment; 62 | Console.WriteLine($"[CHECKED] {amount} transferred! " + 63 | $"(Payments sum for today: {_todaysPaymentsSum})"); 64 | } 65 | else 66 | { 67 | Console.WriteLine($"Transaction limit of " + 68 | $"{MaxDailyPaymentsSum} reached!"); 69 | } 70 | } 71 | catch (OverflowException) 72 | { 73 | Console.WriteLine($"Overflow exception happened!"); 74 | } 75 | } 76 | } 77 | 78 | public void MakePaymentNotChecked(int amount) 79 | { 80 | var paymentsSumAfterPayment = _todaysPaymentsSum + amount; 81 | if (paymentsSumAfterPayment < MaxDailyPaymentsSum) 82 | { 83 | _todaysPaymentsSum = paymentsSumAfterPayment; 84 | Console.WriteLine($"[UNCHECKED] {amount} transferred! " + 85 | $"(Payments sum for today: {_todaysPaymentsSum})"); 86 | } 87 | else 88 | { 89 | Console.WriteLine($"Transaction limit of " + 90 | $"{MaxDailyPaymentsSum} reached!"); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ImmutableTypes/Program.cs: -------------------------------------------------------------------------------- 1 | var immutablePoint = new ImmutablePoint(10, 11); 2 | //we can't change the value of an immutable object, 3 | //so the below line will not compile 4 | //immutablePoint.X = 5; 5 | 6 | var point = new Point(5, 10); 7 | SomeMethod(point); 8 | SomeOtherMethod(point); 9 | Console.WriteLine($"X:{point.X}, Y:{point.Y}"); 10 | 11 | void SomeMethod(Point point) 12 | { 13 | point.X = 500; 14 | } 15 | 16 | void SomeOtherMethod(Point point) 17 | { 18 | } 19 | 20 | var person = new Person("123456789", "John", 1987); 21 | //this will make the person object invalid, 22 | //yet it is allowsed with mutable objects 23 | //person.Id = null; 24 | 25 | //objects used as keys in the dicitonary should be immutable 26 | //otherwise their identity may change over time 27 | var dict = new Dictionary(); 28 | dict[person] = "aaa"; 29 | person.Id = "new id"; 30 | //the below will throw because there is no such key in the dictionary, 31 | //because the hashcode changed because it's built using the Id that changed 32 | //Console.WriteLine(dict[person]); 33 | 34 | if(string.IsNullOrEmpty(person.Name) || 35 | person.Name.Length < 2 || 36 | person.Name.Length > 25) 37 | { 38 | //test this path 39 | } 40 | else 41 | { 42 | //test this path too 43 | } 44 | 45 | var januaryThe1st = new DateTime(2022, 1, 1); 46 | var januaryThe8th = januaryThe1st.AddDays(7); 47 | 48 | Console.ReadKey(); 49 | 50 | public class ImmutablePoint 51 | { 52 | public int X { get; } 53 | public int Y { get; } 54 | 55 | public ImmutablePoint(int x, int y) 56 | { 57 | X = x; 58 | Y = y; 59 | } 60 | } 61 | 62 | public class Point 63 | { 64 | public int X { get; set; } 65 | public int Y { get; set;} 66 | 67 | public Point(int x, int y) 68 | { 69 | X = x; 70 | Y = y; 71 | } 72 | } 73 | 74 | public class Person 75 | { 76 | public Person(string id, string name, int yearOfBirth) 77 | { 78 | if (string.IsNullOrEmpty(id) || 79 | id.Length != 9 || 80 | !id.All(character => char.IsDigit(character))) 81 | { 82 | throw new ArgumentException("Id is invalid"); 83 | } 84 | if (string.IsNullOrEmpty(name) || name.Length < 2 || name.Length > 25) 85 | { 86 | throw new ArgumentException("Name is invalid"); 87 | } 88 | if (yearOfBirth < 1900 || yearOfBirth > DateTime.Now.Year) 89 | { 90 | throw new ArgumentException("YearOfBirth is invalid"); 91 | } 92 | Id = id; 93 | Name = name; 94 | YearOfBirth = yearOfBirth; 95 | } 96 | 97 | public string Id { get; set; } 98 | public string Name { get; set; } 99 | public int YearOfBirth { get; set; } 100 | 101 | public override int GetHashCode() 102 | { 103 | return Id.GetHashCode(); 104 | } 105 | } -------------------------------------------------------------------------------- /Delegates/Program.cs: -------------------------------------------------------------------------------- 1 | //we can assign functions to a variable of delegate type 2 | ProcessString processString1 = TrimTo5Letters; 3 | ProcessString processString2 = ToUpper; 4 | 5 | Console.WriteLine(processString1("Helloooooooooooooo")); 6 | Console.WriteLine(processString2("Helloooooooooooooo")); 7 | 8 | Print print1 = text => Console.WriteLine(text.ToLower()); 9 | Print print2 = text => Console.WriteLine(text.ToUpper()); 10 | Print print3 = print1 + print2; 11 | print3("Crocodile"); 12 | 13 | Print print4 = text => Console.WriteLine(text.Substring(0,3)); 14 | print3 += print4; 15 | print3("Giraffe"); 16 | 17 | //altenatively, we can use Funcs, which are generic delegates 18 | Func processString1Func = TrimTo5Letters; 19 | Func processString2Func = ToUpper; 20 | 21 | Func sumLengths = 22 | (text1, text2) => text1.Length + text2.Length; 23 | 24 | Func sumLengths2 = SumLenghts; 25 | 26 | //to represent a void function, we must use Action instead of Func 27 | Action printToConsole = PrintToConsole; 28 | 29 | //we can't have Funcs or actions with ref or out parameters 30 | //Func funcWithRefOut; 31 | 32 | //also, we can't have Funcs or Actions with optional parameters 33 | //Func funcWithOptionalParameters = 34 | // (text, number = 0) => true; 35 | 36 | //nor with "params" parameters 37 | //Func funcWithParams; 38 | 39 | Func verySpecificFunc; 40 | Calculate superComplexFuncionUsedEverywhereInTheProject; 41 | 42 | Console.ReadKey(); 43 | 44 | void PrintToConsole(string text) 45 | { 46 | Console.WriteLine(text); 47 | } 48 | 49 | int SumLenghts(string text1, string text2) 50 | { 51 | return text1.Length + text2.Length; 52 | } 53 | 54 | string TrimTo5Letters(string input) 55 | { 56 | return input.Substring(0, 5); 57 | } 58 | 59 | string ToUpper(string input) 60 | { 61 | return input.ToUpper(); 62 | } 63 | 64 | delegate string ProcessString(string input); 65 | 66 | delegate void Print(string input); 67 | 68 | delegate float Calculate( 69 | int number, string text, bool flag, DateTime date); 70 | 71 | //built-in Func type is also a delegate 72 | //delegate TReturn Func( 73 | // TInput1 input1, TInput2 input2); 74 | 75 | //delegates, unlike Funcs or Actions, can use ref or out parameters 76 | delegate double DelegateWithRefOut( 77 | out string text, ref int number); 78 | 79 | //..optional parameters 80 | delegate bool DelegateWithOptionalParam( 81 | string text, int number = 0); 82 | 83 | //...and "params" 84 | delegate int DelegateWithParams(params string[] words); 85 | 86 | interface ICommandExecutor 87 | { 88 | void Execute(Func command); 89 | void Execute(RunCommand command); 90 | } 91 | 92 | enum CommandType { Start, Stop, Reset } 93 | 94 | delegate bool RunCommand(CommandType commandType); 95 | -------------------------------------------------------------------------------- /InversionOfControl_WinFormsApp/HelloForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 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 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /Record/Program.cs: -------------------------------------------------------------------------------- 1 | var @record = new Record(5); 2 | var baseTypeForRecord = record.GetType().BaseType; 3 | 4 | var recordStruct = new RecordStruct(5); 5 | var baseTypeForRecordStruct = recordStruct.GetType().BaseType; 6 | 7 | var somePoint = new PointClass(10, 5); 8 | var otherPointEqualByValue = new PointClass(10, 5); 9 | var dict = new Dictionary(); 10 | dict[somePoint] = "aaa"; 11 | dict[otherPointEqualByValue] = "bbb"; 12 | 13 | var areEqual = somePoint.Equals(otherPointEqualByValue); 14 | Console.WriteLine(somePoint); 15 | 16 | var somePointRecord = new PointPositionalRecord(2, 3); 17 | var somePointBythNewY = somePointRecord with { Y = 6 }; 18 | var (_, localY) = somePointBythNewY; 19 | 20 | var pointNonPositionalRecord = new PointNonPositionalRecord(2, 3); 21 | //Deconstruction doesn't work by defaul for non-positional records 22 | //var (localX, _) = pointNonPositionalRecord; 23 | 24 | //also it doesn't work by default for non-positional record structs 25 | var pointNonPositionalRecordStruct = new PointNonPositionalRecordStruct(2, 3); 26 | //var (localXStruct, _) = pointNonPositionalRecordStruct; 27 | 28 | var pointReadonlyRecordStructDefaultValues = new PointReadonlyRecordStruct(); 29 | 30 | Console.ReadKey(); 31 | 32 | 33 | record Record(int a); 34 | record struct RecordStruct(int a); 35 | readonly record struct ReadonlyRecordStruct(int a); 36 | 37 | //only record structs can be readonly 38 | //readonly record Rec2(int a); 39 | 40 | public readonly record struct PointReadonlyRecordStruct(int X, int Y); 41 | 42 | public class PointClass : IEquatable 43 | { 44 | public int X { get; } 45 | public int Y { get; } 46 | 47 | public PointClass(int x, int y) 48 | { 49 | X = x; 50 | Y = y; 51 | } 52 | 53 | public override string ToString() 54 | { 55 | return $"X:{X}, Y:{Y}"; 56 | } 57 | 58 | public override int GetHashCode() 59 | { 60 | return HashCode.Combine(X, Y); 61 | } 62 | 63 | public override bool Equals(object? obj) 64 | { 65 | return obj is PointClass && Equals((PointClass)obj); 66 | } 67 | 68 | public bool Equals(PointClass? other) 69 | { 70 | return other is not null && other.X == X && other.Y == Y; 71 | } 72 | } 73 | 74 | public record PointPositionalRecord(int X, int Y); 75 | 76 | public record PointNonPositionalRecord 77 | { 78 | public int X { get; set; } //non-positional records can be read-write 79 | public int Y { get; set; } 80 | 81 | public PointNonPositionalRecord(int x, int y) 82 | { 83 | X = x; 84 | Y = y; 85 | } 86 | 87 | public int Sum() //we can add methods to records 88 | { 89 | return X + Y; 90 | } 91 | } 92 | 93 | public record struct PointNonPositionalRecordStruct 94 | { 95 | public int X { get; set; } 96 | public int Y { get; set; } 97 | 98 | public PointNonPositionalRecordStruct(int x, int y) 99 | { 100 | X = x; 101 | Y = y; 102 | } 103 | } -------------------------------------------------------------------------------- /Deconstruction/Program.cs: -------------------------------------------------------------------------------- 1 | //we can deconstruct ValueTuples 2 | var numbers = new[] { 1, 4, 2, 6, 11, 5, 83, 1, 2 }; 3 | int count; 4 | double average; 5 | (var sum, count, average) = AnalyzeNumbers(numbers); 6 | 7 | if (count == 0) 8 | { 9 | Console.WriteLine("The collection is empty"); 10 | } 11 | else 12 | { 13 | Console.WriteLine($"The collection has {count}" + 14 | $" elements, with total sum of {sum} " + 15 | $"and average of {average}"); 16 | } 17 | var numbersAverageSize = average > 100 ? 18 | "large" : 19 | "small"; 20 | 21 | Console.WriteLine( 22 | $"The numbers in the collection are " + 23 | $"relatively {numbersAverageSize}"); 24 | 25 | //we can also deconstruct tuples 26 | var tuple = new Tuple("abc", true, 10); 27 | var (text, boolean, number) = tuple; 28 | 29 | //and positional records: 30 | var bob = new Person("Bob", 1950, "USA"); 31 | var (name, _, country) = bob; 32 | 33 | //classes, by default, can't be deconstructed 34 | var hannibal = new PetNoDeconstruct("Hannibal", PetType.Fish, 1.1f); 35 | //var (petName, type, _) = hannibal; 36 | 37 | //but they can be if we implement Deconstruct method 38 | var taiga = new Pet("Taiga", PetType.Dog, 30f); 39 | var (petName, petType, weight) = taiga; 40 | 41 | var date = new DateTime(2020, 1, 8); 42 | var (year, month, day) = date; 43 | 44 | Console.ReadKey(); 45 | 46 | (int sum, int count, double average) AnalyzeNumbers( 47 | IEnumerable numbers) 48 | { 49 | var sum = 0; 50 | var count = 0; 51 | foreach (var number in numbers) 52 | { 53 | sum += number; 54 | count++; 55 | } 56 | var average = (double)sum / count; 57 | return (sum, count, average); 58 | } 59 | 60 | class Pet 61 | { 62 | public string Name { get; } 63 | public PetType PetType { get; } 64 | public float Weight { get; } 65 | 66 | public Pet(string name, PetType petType, float weight) 67 | { 68 | Name = name; 69 | PetType = petType; 70 | Weight = weight; 71 | } 72 | 73 | public void Deconstruct( 74 | out string name, 75 | out PetType petType, 76 | out float weight) 77 | { 78 | name = Name; 79 | petType = PetType; 80 | weight = Weight; 81 | } 82 | } 83 | 84 | class PetNoDeconstruct 85 | { 86 | public string Name { get; } 87 | public PetType PetType { get; } 88 | public float Weight { get; } 89 | 90 | public PetNoDeconstruct(string name, PetType petType, float weight) 91 | { 92 | Name = name; 93 | PetType = petType; 94 | Weight = weight; 95 | } 96 | } 97 | 98 | public enum PetType { Cat, Dog, Fish } 99 | 100 | record Person(string Name, int YearOfBirth, string Country); 101 | 102 | static class DateTimeExtensions 103 | { 104 | public static void Deconstruct( 105 | this DateTime date, 106 | out int year, 107 | out int month, 108 | out int day) 109 | { 110 | year = date.Year; 111 | month = date.Month; 112 | day = date.Day; 113 | } 114 | } 115 | 116 | -------------------------------------------------------------------------------- /ObserverDesignPattern/Program.cs: -------------------------------------------------------------------------------- 1 | var bitcoinPriceReader = new BitcoinPriceReader(); 2 | 3 | var emailPriceChangeNotifier = new EmailPriceChangeNotifier(25000); 4 | bitcoinPriceReader.AttachObserver(emailPriceChangeNotifier); 5 | 6 | var pushPriceChangeNotifier = new PushPriceChangeNotifier(40000); 7 | bitcoinPriceReader.AttachObserver(pushPriceChangeNotifier); 8 | 9 | bitcoinPriceReader.ReadCurrentPrice(); 10 | bitcoinPriceReader.ReadCurrentPrice(); 11 | 12 | Console.WriteLine("Push notifications OFF"); 13 | bitcoinPriceReader.DetachObserver(pushPriceChangeNotifier); 14 | 15 | bitcoinPriceReader.ReadCurrentPrice(); 16 | 17 | Console.ReadKey(); 18 | 19 | public interface IObserver 20 | { 21 | void Update(TData data); 22 | } 23 | 24 | public interface IObservable 25 | { 26 | void AttachObserver(IObserver observer); 27 | void DetachObserver(IObserver observer); 28 | void NotifyObservers(); 29 | } 30 | 31 | public class BitcoinPriceReader : IObservable 32 | { 33 | private decimal _currentBitcoinPrice; 34 | private List> _observers = 35 | new List>(); 36 | 37 | public void AttachObserver(IObserver observer) 38 | { 39 | _observers.Add(observer); 40 | } 41 | 42 | public void DetachObserver(IObserver observer) 43 | { 44 | _observers.Remove(observer); 45 | } 46 | 47 | public void NotifyObservers() 48 | { 49 | foreach (var observer in _observers) 50 | { 51 | observer.Update(_currentBitcoinPrice); 52 | } 53 | } 54 | 55 | public void ReadCurrentPrice() 56 | { 57 | _currentBitcoinPrice = new Random().Next(0, 50000); 58 | 59 | NotifyObservers(); 60 | } 61 | } 62 | 63 | public class EmailPriceChangeNotifier : IObserver 64 | { 65 | private readonly decimal _notificationThreshold; 66 | 67 | public EmailPriceChangeNotifier(decimal notificationThreshold) 68 | { 69 | _notificationThreshold = notificationThreshold; 70 | } 71 | 72 | public void Update(decimal currentBitcoinPrice) 73 | { 74 | if (currentBitcoinPrice > _notificationThreshold) 75 | { 76 | Console.WriteLine($"Sending an email saying that " + 77 | $"the Bitcoin price exceeded {_notificationThreshold} " + 78 | $"and is now {currentBitcoinPrice}\n"); 79 | } 80 | } 81 | } 82 | 83 | public class PushPriceChangeNotifier : IObserver 84 | { 85 | private readonly decimal _notificationThreshold; 86 | 87 | public PushPriceChangeNotifier(decimal notificationThreshold) 88 | { 89 | _notificationThreshold = notificationThreshold; 90 | } 91 | 92 | public void Update(decimal currentBitcoinPrice) 93 | { 94 | if (currentBitcoinPrice > _notificationThreshold) 95 | { 96 | Console.WriteLine($"Sending a push notification saying that " + 97 | $"the Bitcoin price exceeded {_notificationThreshold} " + 98 | $"and is now {currentBitcoinPrice}\n"); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /Strategy/Program.cs: -------------------------------------------------------------------------------- 1 | var games = new List 2 | { 3 | new Game( 4 | "Stardew Valley", 19.99m, 98, 5 | new DateTime(2016, 2, 26), true), 6 | new Game( 7 | "Red Dead Redemption II", 60m, 92, 8 | new DateTime(2018, 10, 26), true), 9 | new Game( 10 | "Spiritfarer", 25m, 95, 11 | new DateTime(2020, 8, 18), false), 12 | new Game( 13 | "Heroes III", 10m, 82, 14 | new DateTime(1999, 3, 3), false), 15 | new Game( 16 | "God of War", 60m, 97, 17 | new DateTime(2018, 4, 20), true), 18 | 19 | }; 20 | 21 | var selectedOption = FilteringType.BestGames; 22 | var searchWord = "Red"; 23 | 24 | //Code without strategy pattern 25 | 26 | //IEnumerable filteredGames = null; 27 | //switch (selectedOption) 28 | //{ 29 | // case FilteringType.ByTitle: 30 | // filteredGames = FindByTitle(games, searchWord); 31 | // break; 32 | // case FilteringType.BestGames: 33 | // filteredGames = FindBestGames(games); 34 | // break; 35 | // case FilteringType.GamesOfThisYear: 36 | // filteredGames = FindGamesOfThisYear(games); 37 | // break; 38 | // case FilteringType.BestDeals: 39 | // filteredGames = FindBestDeals(games); 40 | // break; 41 | //} 42 | 43 | var strategy = SelectStrategy(selectedOption, searchWord); 44 | 45 | var filteredGames = FindBy(strategy, games); 46 | foreach (var game in filteredGames) 47 | { 48 | Console.WriteLine(game); 49 | } 50 | 51 | Console.ReadKey(); 52 | 53 | Func SelectStrategy( 54 | FilteringType selectedOption, string searchWord) 55 | { 56 | switch (selectedOption) 57 | { 58 | case FilteringType.ByTitle: 59 | return game => game.Title.Contains(searchWord); 60 | case FilteringType.BestGames: 61 | return game => game.Rating > 95; 62 | case FilteringType.GamesOfThisYear: 63 | return game => game.ReleaseDate.Year == 64 | DateTime.Now.Year; 65 | case FilteringType.BestDeals: 66 | return game => game.Price < 25; 67 | default: 68 | throw new ArgumentException("Invalid option"); 69 | } 70 | } 71 | 72 | IEnumerable FindByTitle( 73 | IEnumerable games, 74 | string searchWord) 75 | { 76 | return games.Where(g => g.IsAvailable && 77 | g.Title.Contains(searchWord)); 78 | } 79 | 80 | IEnumerable FindBestGames( 81 | IEnumerable games) 82 | { 83 | return games.Where(g => g.IsAvailable && 84 | g.Rating > 95); 85 | } 86 | 87 | IEnumerable FindGamesOfThisYear( 88 | IEnumerable games) 89 | { 90 | return games.Where(g => g.IsAvailable && 91 | g.ReleaseDate.Year == DateTime.Now.Year); 92 | } 93 | 94 | IEnumerable FindBestDeals( 95 | IEnumerable games) 96 | { 97 | return games.Where(g => g.IsAvailable && 98 | g.Price < 25); 99 | } 100 | 101 | IEnumerable FindBy( 102 | Func strategy, 103 | IEnumerable games) 104 | { 105 | return games.Where(g => g.IsAvailable && strategy(g)); 106 | } 107 | 108 | record Game( 109 | string Title, 110 | decimal Price, 111 | decimal Rating, 112 | DateTime ReleaseDate, 113 | bool IsAvailable); 114 | 115 | enum FilteringType 116 | { 117 | ByTitle, 118 | BestGames, 119 | GamesOfThisYear, 120 | BestDeals 121 | } -------------------------------------------------------------------------------- /Events/Program.cs: -------------------------------------------------------------------------------- 1 | var bitcoinPriceReader = new BitcoinPriceReader(); 2 | 3 | //events and delegate-type fields seems similar... 4 | //bitcoinPriceReader.PriceRead += SomeMethod; 5 | //bitcoinPriceReader.PriceReadNotAnEvent += SomeMethod; 6 | 7 | //...but we can't invoke an event from outside of the class it belongs to 8 | //bitcoinPriceReader.PriceRead(100); 9 | 10 | var emailPriceChangeNotifier = new EmailPriceChangeNotifier(25000); 11 | var pushPriceChangeNotifier = new PushPriceChangeNotifier(40000); 12 | 13 | bitcoinPriceReader.PriceRead += emailPriceChangeNotifier.Update; 14 | bitcoinPriceReader.PriceRead += pushPriceChangeNotifier.Update; 15 | 16 | bitcoinPriceReader.ReadCurrentPrice(); 17 | bitcoinPriceReader.ReadCurrentPrice(); 18 | 19 | //it's a good practice to unsubscribe from event handler 20 | bitcoinPriceReader.PriceRead -= emailPriceChangeNotifier.Update; 21 | bitcoinPriceReader.PriceRead -= pushPriceChangeNotifier.Update; 22 | 23 | Console.ReadKey(); 24 | 25 | void SomeMethod(decimal price) 26 | { 27 | Console.WriteLine($"Price is {price}"); 28 | } 29 | 30 | public class BitcoinPriceReader 31 | { 32 | private int _currentBitcoinPrice; 33 | 34 | //we can use custom delegate for events 35 | //public event PriceRead? PriceRead; 36 | //public PriceRead? PriceReadNonEvent; 37 | 38 | //or the built-in EventHandler delegate 39 | public event EventHandler PriceRead; 40 | 41 | public void ReadCurrentPrice() 42 | { 43 | _currentBitcoinPrice = new Random().Next(0, 50000); 44 | OnPriceRead(_currentBitcoinPrice); 45 | } 46 | 47 | private void OnPriceRead(decimal price) 48 | { 49 | PriceRead?.Invoke(this, new PriceReadEventArgs(price)); 50 | } 51 | } 52 | 53 | public delegate void PriceRead(decimal price); 54 | 55 | public class EmailPriceChangeNotifier 56 | { 57 | private readonly decimal _notificationThreshold; 58 | 59 | public EmailPriceChangeNotifier(decimal notificationThreshold) 60 | { 61 | _notificationThreshold = notificationThreshold; 62 | } 63 | 64 | public void Update(object sender, PriceReadEventArgs eventArgs) 65 | { 66 | if (eventArgs.Price > _notificationThreshold) 67 | { 68 | Console.WriteLine($"Sending an email saying that " + 69 | $"the Bitcoin price exceeded {_notificationThreshold} " + 70 | $"and is now {eventArgs.Price}\n"); 71 | } 72 | } 73 | } 74 | 75 | public class PushPriceChangeNotifier 76 | { 77 | private readonly decimal _notificationThreshold; 78 | 79 | public PushPriceChangeNotifier(decimal notificationThreshold) 80 | { 81 | _notificationThreshold = notificationThreshold; 82 | } 83 | 84 | public void Update(object sender, PriceReadEventArgs eventArgs) 85 | { 86 | if (eventArgs.Price > _notificationThreshold) 87 | { 88 | Console.WriteLine($"Sending a push notification saying that " + 89 | $"the Bitcoin price exceeded {_notificationThreshold} " + 90 | $"and is now {eventArgs.Price}\n"); 91 | } 92 | } 93 | } 94 | 95 | public delegate void PriceReadEventHandler( 96 | object sender, PriceReadEventArgs e); 97 | 98 | public class PriceReadEventArgs : EventArgs 99 | { 100 | public decimal Price { get; } 101 | 102 | public PriceReadEventArgs(decimal price) 103 | { 104 | Price = price; 105 | } 106 | } -------------------------------------------------------------------------------- /TemplateMethod/Program.cs: -------------------------------------------------------------------------------- 1 | var settlersOfCatan = new SettlersOfCatan(); 2 | settlersOfCatan.Play(); 3 | 4 | Console.WriteLine(); 5 | 6 | var terraformingMars = new TerraformingMars(); 7 | terraformingMars.Play(); 8 | 9 | Console.ReadKey(); 10 | 11 | abstract class BoardGame 12 | { 13 | protected Random Random = new Random(); 14 | 15 | public void Play() 16 | { 17 | SetupBoard(); 18 | bool isFinished = false; 19 | while (!isFinished) 20 | { 21 | isFinished = PlayTurn(); 22 | } 23 | SelectWinner(); 24 | } 25 | 26 | protected abstract void SetupBoard(); 27 | protected abstract bool PlayTurn(); 28 | protected abstract void SelectWinner(); 29 | } 30 | 31 | class SettlersOfCatan : BoardGame 32 | { 33 | protected override void SetupBoard() 34 | { 35 | Console.WriteLine("Randomly placing hexagonal tiles."); 36 | } 37 | 38 | protected override bool PlayTurn() 39 | { 40 | Console.WriteLine("Building, trading, etc."); 41 | return Random.Next(5) >= 4; 42 | } 43 | 44 | protected override void SelectWinner() 45 | { 46 | Console.WriteLine( 47 | "Winner is the one who first got 12 points"); 48 | } 49 | } 50 | 51 | class TerraformingMars : BoardGame 52 | { 53 | private Random _random = new Random(); 54 | 55 | protected override void SetupBoard() 56 | { 57 | Console.WriteLine("Choosing from two available maps."); 58 | } 59 | 60 | protected override bool PlayTurn() 61 | { 62 | Console.WriteLine( 63 | "Raising oxygen level, placing oceans, etc."); 64 | return _random.Next(5) >= 4; 65 | } 66 | 67 | protected override void SelectWinner() 68 | { 69 | Console.WriteLine( 70 | "Winner is the one with most points at game's end."); 71 | } 72 | } 73 | 74 | //below is the code that does not use the Template Method 75 | 76 | //class SettlersOfCatan 77 | //{ 78 | // private Random _random = new Random(); 79 | 80 | // public void Play() 81 | // { 82 | // SetupBoard(); 83 | // bool isFinished = false; 84 | // while (!isFinished) 85 | // { 86 | // isFinished = PlayTurn(); 87 | // } 88 | // SelectWinner(); 89 | // } 90 | 91 | // private void SetupBoard() 92 | // { 93 | // Console.WriteLine("Randomly placing hexagonal tiles."); 94 | // } 95 | 96 | // private bool PlayTurn() 97 | // { 98 | // Console.WriteLine("Building, trading, etc."); 99 | // return _random.Next(5) >= 4; 100 | // } 101 | 102 | // private void SelectWinner() 103 | // { 104 | // Console.WriteLine( 105 | // "Winner is the one who first got 12 points"); 106 | // } 107 | //} 108 | 109 | //class TerraformingMars 110 | //{ 111 | // private Random _random = new Random(); 112 | 113 | // public void Play() 114 | // { 115 | // SetupBoard(); 116 | // bool isFinished = false; 117 | // while (!isFinished) 118 | // { 119 | // isFinished = PlayTurn(); 120 | // } 121 | // SelectWinner(); 122 | // } 123 | 124 | // private void SetupBoard() 125 | // { 126 | // Console.WriteLine("Choosing from two available maps."); 127 | // } 128 | 129 | // private bool PlayTurn() 130 | // { 131 | // Console.WriteLine( 132 | // "Raising oxygen level, placing oceans, etc."); 133 | // return _random.Next(5) >= 4; 134 | // } 135 | 136 | // private void SelectWinner() 137 | // { 138 | // Console.WriteLine( 139 | // "Winner is the one with most points at game's end."); 140 | // } 141 | //} -------------------------------------------------------------------------------- /NullableReferenceTypes/Program.cs: -------------------------------------------------------------------------------- 1 | //the compiler gives us a warning, 2 | //because we assign null to non-nullable type 3 | using NUnit.Framework; 4 | 5 | string nonNullableTextBeingNull = null; 6 | 7 | string? nullableText = null; 8 | string nonNullableText = "hello!"; 9 | 10 | Console.WriteLine( 11 | "Nullable text length" + GetLength(nullableText)); 12 | Console.WriteLine( 13 | "Non-Nullable text length" + GetLength(nonNullableText)); 14 | 15 | var array = new string[10]; 16 | Console.WriteLine(array[0].Length); 17 | 18 | //the nullable reference types feature can be enabled/disabled per project 19 | //but we can also enable/disable it manually per file or a code fragment 20 | #nullable disable 21 | string text = null; 22 | Console.WriteLine(text); 23 | #nullable enable 24 | 25 | Console.ReadKey(); 26 | 27 | int GetLength(string? nullableText) 28 | { 29 | if(nullableText == null) 30 | { 31 | return 0; 32 | } 33 | return nullableText.Length; 34 | } 35 | 36 | string FormatHousesData(IEnumerable houses) 37 | { 38 | return string.Join("\n", 39 | houses.Select(house => 40 | $"Owner is {house.OwnerName}, " + 41 | $"address is {house.Address.Number} " + 42 | $"{house.Address.Street}")); 43 | } 44 | 45 | bool ValidateAddress(House house) 46 | { 47 | if(house == null) 48 | { 49 | Console.WriteLine("house is null"); 50 | return false; 51 | } 52 | if(house.Address == null) 53 | { 54 | Console.WriteLine("address is null"); 55 | return false; 56 | } 57 | if(house.Address.Number == null) 58 | { 59 | Console.WriteLine("address/number is null"); 60 | return false; 61 | } 62 | if(house.Address.Street == null) 63 | { 64 | Console.WriteLine("address/street is null"); 65 | return false; 66 | } 67 | if(house.Address.Number.Length == 0) 68 | { 69 | Console.WriteLine("address/number is empty"); 70 | return false; 71 | } 72 | if (house.Address.Street.Length == 0) 73 | { 74 | Console.WriteLine("address/street is empty"); 75 | return false; 76 | } 77 | return true; 78 | } 79 | 80 | class House 81 | { 82 | public string OwnerName { get; } 83 | public Address Address { get; } 84 | 85 | public House(string ownerName, Address address) 86 | { 87 | if(ownerName == null) 88 | { 89 | throw new ArgumentNullException(nameof(ownerName)); 90 | } 91 | if (address == null) 92 | { 93 | throw new ArgumentNullException(nameof(address)); 94 | } 95 | OwnerName = ownerName; 96 | Address = address; 97 | } 98 | } 99 | 100 | class Address 101 | { 102 | public string Street { get; } 103 | public string Number { get; } 104 | 105 | public Address(string street, string number) 106 | { 107 | Street = street; 108 | Number = number; 109 | } 110 | } 111 | 112 | class Calculator 113 | { 114 | public int Add(int a, int b) => a + b; 115 | } 116 | 117 | [TestFixture] 118 | public class CalculatorTests 119 | { 120 | private Calculator? _cut; 121 | 122 | [SetUp] 123 | public void SetUp() 124 | { 125 | _cut = new Calculator(); 126 | } 127 | 128 | [Test] 129 | public void Add5And10_ShallGive15() 130 | { 131 | Assert.AreEqual(15, _cut!.Add(10, 5)); 132 | } 133 | } 134 | 135 | [TestFixture] 136 | public class HouseTests 137 | { 138 | [Test] 139 | public void NullOwnerName_ShallThrowException() 140 | { 141 | Assert.Throws(() => 142 | new House(null!, new Address("Maple Street", "12B"))); 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /Cohesion/Program.cs: -------------------------------------------------------------------------------- 1 | var house = new House("123 Maple Road", 155, 1); 2 | var ownersDatabase = new OwnersDatabase(); 3 | var housePricerLowCohesion = new HousePricerLowCohesion(2000, ownersDatabase); 4 | housePricerLowCohesion.SendPriceToOwner(house); 5 | 6 | var housePricer = new HousePricer(2000); 7 | var price = housePricer.GetPrice(house); 8 | var ownerNotifier = new OwnerNotifier(ownersDatabase); 9 | ownerNotifier.SendPriceToOwner(price, house.Address); 10 | 11 | Console.ReadKey(); 12 | 13 | //this class is highly cohesive 14 | class PetsCollection 15 | { 16 | private List _pets = new (); 17 | 18 | public void Add(Pet pet) => _pets.Add(pet); 19 | public int Count => _pets.Count; 20 | public IEnumerable GetCurrentlyStoredTypes() => 21 | _pets.Select(pet => pet.PetType).Distinct(); 22 | public bool Contains(PetType petType) => 23 | GetCurrentlyStoredTypes().Any(type => type == petType); 24 | } 25 | 26 | public record Pet(string Name, PetType PetType, float Weight); 27 | public enum PetType { Cat, Dog, Fish } 28 | 29 | //this class is not cohesive 30 | public class HousePricerLowCohesion 31 | { 32 | private IOwnersDatabase _ownersDatabase; 33 | private decimal _dollarsPerSquareMeter; 34 | public HousePricerLowCohesion( 35 | decimal dollarsPerSquareMeter, 36 | IOwnersDatabase ownersDatabase) 37 | { 38 | _dollarsPerSquareMeter = dollarsPerSquareMeter; 39 | _ownersDatabase = ownersDatabase; 40 | } 41 | 42 | public decimal GetPrice(House house) => 43 | _dollarsPerSquareMeter * (decimal)house.Area * 44 | GetPriceMultiplierBasedOnFloors(house.Floors); 45 | 46 | private decimal GetPriceMultiplierBasedOnFloors(int floors) => 47 | floors switch { 1 => 1m, 2 => 1.5m, _ => 1.6m }; 48 | 49 | public void SendPriceToOwner(House house) => 50 | Console.WriteLine($"Sending price {GetPrice(house)}" + 51 | $" to {FindOwnerEmail(house.Address)}"); 52 | 53 | private string FindOwnerEmail(string address) => 54 | _ownersDatabase.GetEmailByAddress(address); 55 | } 56 | 57 | //the above class can be split into two highly-cohesive classes 58 | public class HousePricer 59 | { 60 | private decimal _dollarsPerSquareMeter; 61 | public HousePricer(decimal dollarsPerSquareMeter) 62 | { 63 | _dollarsPerSquareMeter = dollarsPerSquareMeter; 64 | } 65 | 66 | public decimal GetPrice(House house) => 67 | _dollarsPerSquareMeter * (decimal)(house.Area) * 68 | GetPriceMultiplierBasedOnFloors(house.Floors); 69 | 70 | private decimal GetPriceMultiplierBasedOnFloors(int floors) => 71 | floors switch { 1 => 1m, 2 => 1.5m, _ => 1.6m }; 72 | } 73 | 74 | public class OwnerNotifier 75 | { 76 | private IOwnersDatabase _ownersDatabase; 77 | public OwnerNotifier(IOwnersDatabase ownersDatabase) 78 | { 79 | _ownersDatabase = ownersDatabase; 80 | } 81 | 82 | public void SendPriceToOwner(decimal price, string address) => 83 | Console.WriteLine($"Sending price price" + 84 | $" to {FindOwnerEmail(address)}"); 85 | 86 | private string FindOwnerEmail(string address) => 87 | _ownersDatabase.GetEmailByAddress(address); 88 | } 89 | 90 | public record House(string Address, double Area, int Floors); 91 | 92 | public interface IOwnersDatabase 93 | { 94 | string GetEmailByAddress(string address); 95 | } 96 | 97 | public class OwnersDatabase : IOwnersDatabase 98 | { 99 | public string GetEmailByAddress(string address) 100 | { 101 | if(address == "123 Maple Road") 102 | { 103 | return "john_smith@mail.com"; 104 | } 105 | throw new InvalidOperationException("Unknown address"); 106 | } 107 | } -------------------------------------------------------------------------------- /TupleVsValueTuple/Program.cs: -------------------------------------------------------------------------------- 1 | //Tuple.Create is the simplest way to create a tuple 2 | var tuple = Tuple.Create(1, "aaa"); 3 | //we can also use the constructor, but we must provide type parameters 4 | var tupleCreatedWithConstructor = new Tuple(1, "aaa"); 5 | //tuple can have up to 8 values, so the below will not compile: 6 | //var hugeTuple = Tuple.Create(1, 2, 3, 4, 5, 6, 7, 8, 9); 7 | 8 | //tuples are reference types, so they are compared by reference 9 | var tuple1 = Tuple.Create(1, "aaa"); 10 | var tuple2 = Tuple.Create(1, "aaa"); 11 | Console.WriteLine("tuple1 == tuple2: " + (tuple1 == tuple2)); 12 | //please note that if we need to compare tuples by value, we can 13 | //we must use the Equals method then: 14 | Console.WriteLine("tuple1.Equals(tuple2) " + tuple1.Equals(tuple2)); 15 | 16 | //ValueTuples are value types, so they are compared by value 17 | var valueTuple = new ValueTuple(3, "ccc"); 18 | var valueTuple1 = (2, "bbb"); 19 | var valueTuple2 = (2, "bbb"); 20 | Console.WriteLine("valueTuple1 == valueTuple2: " + 21 | (valueTuple1 == valueTuple2)); 22 | 23 | var dictionaryTuple = new Dictionary, string>(); 24 | dictionaryTuple[Tuple.Create(1, "aaa")] = "some value 1"; 25 | Console.WriteLine(dictionaryTuple[Tuple.Create(1, "aaa")]); 26 | 27 | //tuples are immutable, so the below will not compile 28 | //tuple1.Item1 = 5; 29 | 30 | //value tuples are mutable: 31 | valueTuple1.Item1 = 5; 32 | 33 | //we can't name tuple's items as we want, we are forced to use "Item1" 34 | var numberFromTuple = tuple1.Item1; 35 | 36 | //for value tuples, we can use names we like 37 | var valueTuple3 = (number: 2, text: "ccc"); 38 | var numberFromValueTuple = valueTuple3.number; 39 | //...but Item1 and Item2 still works: 40 | var numberFromValueTuple1 = valueTuple1.Item1; 41 | 42 | //but if we skip the name, the defaults are the same as with tuples: 43 | var numberFromValueTuple2 = valueTuple2.Item1; 44 | 45 | //When working in a small scope, it's easy to follow that Item1 or Item2 means 46 | //but if, for example, the tuple is a result of a method, it becomes complicated. 47 | //For example, this is not very readable: 48 | var result1 = SumCollectionTuple( 49 | new int[] { 1, 2, 3, 1, 4, 1 }); 50 | Console.WriteLine( 51 | $"Calculation result is: {result1.Item1}, {result1.Item2}"); 52 | //we need to actually look into the SumCollectionValueTuple to understand what 53 | //Item1 and Item2 mean 54 | 55 | //this is much better: 56 | var result2 = SumCollectionValueTuple( 57 | new int[] { 1, 2, 3, 1, 4, 1 }); 58 | Console.WriteLine( 59 | $"Calculation result is: {result2.sum}, {result2.count}"); 60 | 61 | //ValueTuples support deconstruction 62 | //deconstruction breaks down the tuple into separate variables 63 | var (sum, count) = SumCollectionValueTuple(new int[] { 1, 2, 3, 1, 4, 1 }); 64 | 65 | //we can declare ValueTuples with more than 8 items 66 | var hugeValueTuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); 67 | var last = hugeValueTuple.Item12; 68 | Console.ReadKey(); 69 | 70 | (int sum, int count) SumCollectionValueTuple(IEnumerable values) 71 | { 72 | return (values.Sum(), values.Count()); 73 | } 74 | 75 | Tuple SumCollectionTuple(IEnumerable values) 76 | { 77 | return Tuple.Create(values.Sum(), values.Count()); 78 | } 79 | 80 | Tuple GetSummaryAboutCollection(IEnumerable values) 81 | { 82 | var sum = values.Sum(); 83 | var count = values.Count(); 84 | return new Tuple(sum, count); 85 | } 86 | 87 | //the alternative would be to use custom types, but this is awkward 88 | //if the type will not be reused in different context 89 | 90 | //SumAndCount GetSummaryAboutCollection(IEnumerable values) 91 | //{ 92 | // var sum = values.Sum(); 93 | // var count = values.Count(); 94 | // return new SumAndCount { Sum = sum, Count = count }; 95 | //} 96 | 97 | //struct SumAndCount 98 | //{ 99 | // public int Sum; 100 | // public int Count; 101 | //} -------------------------------------------------------------------------------- /DependencyInjection/Program.cs: -------------------------------------------------------------------------------- 1 | namespace DependencyInjection; 2 | 3 | public class Program 4 | { 5 | public static void Main(string[] args) 6 | { 7 | //creation of objects 8 | var logger = new Logger(); 9 | var peopleDataReader = new PeopleDataReader(logger); 10 | var formatterFactory = new FormatterFactory(); 11 | var personalDataFormatter = new PersonalDataFormatter( 12 | peopleDataReader, 13 | logger, 14 | formatterFactory); 15 | 16 | //actual run of the application 17 | Console.WriteLine(personalDataFormatter.Format(false)); 18 | 19 | Console.ReadKey(); 20 | } 21 | } 22 | 23 | class PersonalDataFormatterWithFunc 24 | { 25 | private readonly Func> _readPeople; 26 | 27 | public PersonalDataFormatterWithFunc( 28 | Func> readPeople) 29 | { 30 | _readPeople = readPeople; 31 | } 32 | 33 | public string Format() 34 | { 35 | var people = _readPeople(); 36 | 37 | return string.Join("\n", 38 | people.Select(p => $"{p.Name} born in" + 39 | $" {p.Country} on {p.YearOfBirth}")); 40 | } 41 | } 42 | 43 | class PersonalDataFormatter 44 | { 45 | private readonly ILogger _logger; 46 | private readonly IPeopleDataReader _peopleDataReader; 47 | private readonly IFormatterFactory _formatterFactory; 48 | 49 | public PersonalDataFormatter( 50 | IPeopleDataReader peopleDataReader, 51 | ILogger logger, 52 | IFormatterFactory formatterFactory) 53 | { 54 | _peopleDataReader = peopleDataReader; 55 | _logger = logger; 56 | _formatterFactory = formatterFactory; 57 | } 58 | 59 | public string Format(bool isDefaultFormatting) 60 | { 61 | _logger.Log("Formatter running..."); 62 | var people = _peopleDataReader.ReadPeople(); 63 | 64 | if (isDefaultFormatting) 65 | { 66 | return string.Join("\n", 67 | people.Select(p => $"{p.Name} born in" + 68 | $" {p.Country} on {p.YearOfBirth}")); 69 | } 70 | var formatter = _formatterFactory.Create(); 71 | return formatter.Format(people); 72 | } 73 | } 74 | 75 | class PersonalDataFormatterWithoutDependencyInjection 76 | { 77 | public string Format() 78 | { 79 | var peopleDataReader = new PeopleDataReader(new Logger()); 80 | 81 | var people = peopleDataReader.ReadPeople(); 82 | return string.Join("\n", 83 | people.Select(p => $"{p.Name} born in" + 84 | $" {p.Country} on {p.YearOfBirth}")); 85 | } 86 | } 87 | 88 | interface IPeopleDataReader 89 | { 90 | IEnumerable ReadPeople(); 91 | } 92 | 93 | class PeopleDataReader : IPeopleDataReader 94 | { 95 | private readonly ILogger _logger; 96 | 97 | public PeopleDataReader(ILogger logger) 98 | { 99 | _logger = logger; 100 | } 101 | 102 | public IEnumerable ReadPeople() 103 | { 104 | _logger.Log("Reading from database"); 105 | return new List 106 | { 107 | new Person("John", 1982, "USA"), 108 | new Person("Aja", 1992, "India"), 109 | new Person("Tom", 1954, "Australia"), 110 | }; 111 | } 112 | } 113 | 114 | record Person(string Name, int YearOfBirth, string Country); 115 | 116 | interface ILogger 117 | { 118 | void Log(string message); 119 | } 120 | 121 | class Logger : ILogger 122 | { 123 | public void Log(string message) 124 | { 125 | Console.WriteLine(message); 126 | } 127 | } 128 | 129 | interface IFormatterFactory 130 | { 131 | IFormatter Create(); 132 | } 133 | 134 | class FormatterFactory : IFormatterFactory 135 | { 136 | public IFormatter Create() 137 | { 138 | return new NameOnlyFormatter(); 139 | } 140 | } 141 | 142 | interface IFormatter 143 | { 144 | string Format(IEnumerable people); 145 | } 146 | 147 | class NameOnlyFormatter : IFormatter 148 | { 149 | public string Format(IEnumerable people) 150 | { 151 | return string.Join("\n", 152 | people.Select(p => p.Name)); 153 | } 154 | } -------------------------------------------------------------------------------- /CatchException/Program.cs: -------------------------------------------------------------------------------- 1 | public class Program 2 | { 3 | public static void Main(string[] args) 4 | { 5 | try 6 | { 7 | var numbers = Enumerable.Empty(); 8 | var first = GetFirstOrDefault(numbers); 9 | 10 | //let's make the application crash on purpose: 11 | throw new Exception("Unknown exception"); 12 | } 13 | //global catch block is one of the few places 14 | //where catch(Exception) is appropriate 15 | catch (Exception ex) 16 | { 17 | //writing to some application logs would be appropriate here 18 | Console.ForegroundColor = ConsoleColor.Red; 19 | Console.WriteLine($"An unexpected error happened and " + 20 | $"the application can't continue. The error message is" + 21 | $" '{ex.Message}', stack trace is : {ex.StackTrace}"); 22 | } 23 | Console.ReadKey(); 24 | } 25 | 26 | private static T? GetFirstOrDefault(IEnumerable items) 27 | { 28 | try 29 | { 30 | return items.First(); 31 | } 32 | catch (InvalidOperationException) 33 | { 34 | Console.WriteLine("The collection is empty!"); 35 | return default(T); 36 | } 37 | } 38 | 39 | private static double Average(IEnumerable numbers) 40 | { 41 | if(numbers == null) 42 | { 43 | throw new ArgumentNullException( 44 | "The numbers collection is null!"); 45 | } 46 | double sum = 0; 47 | int count = 0; 48 | foreach (var number in numbers) 49 | { 50 | sum += number; 51 | count++; 52 | } 53 | if(count > 0) 54 | { 55 | return sum / count; 56 | } 57 | throw new InvalidOperationException( 58 | "The collection is empty!"); 59 | } 60 | 61 | public class GuiLayer 62 | { 63 | private BusinessLayer _businessLayer; 64 | private ILogger _logger; 65 | 66 | public GuiLayer( 67 | BusinessLayer businessLayer, 68 | ILogger logger) 69 | { 70 | _businessLayer = businessLayer; 71 | _logger = logger; 72 | } 73 | 74 | public void ShowToUser() 75 | { 76 | try 77 | { 78 | var data = _businessLayer.GetProcessedData(); 79 | Console.WriteLine($"Showing to user: {data}"); 80 | } 81 | catch(Exception ex) 82 | { 83 | _logger.LogError("Error in GUI Layer: " + ex); 84 | Console.ForegroundColor = ConsoleColor.Red; 85 | Console.WriteLine($"An unexpected error: '{ex.Message}'"); 86 | } 87 | } 88 | } 89 | 90 | public class BusinessLayer 91 | { 92 | private ILogger _logger; 93 | private DataAccessLayer _dataAccessLayer; 94 | 95 | public BusinessLayer( 96 | DataAccessLayer dataAccessLayer, 97 | ILogger logger) 98 | { 99 | _dataAccessLayer = dataAccessLayer; 100 | _logger = logger; 101 | } 102 | 103 | public string GetProcessedData() 104 | { 105 | try 106 | { 107 | var rawData = _dataAccessLayer.GetRawData(); 108 | return rawData.Trim(); 109 | } 110 | catch(Exception ex) 111 | { 112 | _logger.LogError("Error in BusinessLayer: " + ex); 113 | throw; //rethrowing the exception 114 | } 115 | } 116 | } 117 | 118 | public class DataAccessLayer 119 | { 120 | private readonly ILogger _logger; 121 | 122 | public DataAccessLayer(ILogger logger) 123 | { 124 | _logger = logger; 125 | } 126 | 127 | public string GetRawData() 128 | { 129 | try 130 | { 131 | return " some raw data "; 132 | } 133 | catch (Exception ex) 134 | { 135 | _logger.LogError("Error in DataAccessLayer: " + ex); 136 | throw; //rethrowing the exception 137 | } 138 | } 139 | } 140 | 141 | public interface ILogger 142 | { 143 | void LogError(string message); 144 | } 145 | } 146 | 147 | -------------------------------------------------------------------------------- /Mocks/Mocks.cs: -------------------------------------------------------------------------------- 1 | using Moq; 2 | using NUnit.Framework; 3 | 4 | namespace Mocks 5 | { 6 | //public class Program 7 | //{ 8 | // //in production code we would use a real DatabasePeopleDataReader 9 | // //in tests, we will use mock 10 | // //(this code is commented as the type of this project is class library, 11 | // //not the Console Application 12 | 13 | // public static void Main(string[] args) 14 | // { 15 | // var personalDataFormatter = new PersonalDataFormatter( 16 | // new DatabasePeopleDataReader()); 17 | 18 | // Console.WriteLine(personalDataFormatter.Format()); 19 | 20 | // var enthusiasticGreeter = new EnthusiasticGreeter( 21 | // message => Console.WriteLine(message)); 22 | 23 | // enthusiasticGreeter.PrintHelloNTimes(5); 24 | 25 | // Console.ReadKey(); 26 | // } 27 | //} 28 | 29 | public class EnthusiasticGreeter 30 | { 31 | readonly Action _printToConsole; 32 | 33 | public EnthusiasticGreeter(Action printToConsole) 34 | { 35 | _printToConsole = printToConsole; 36 | } 37 | 38 | public void PrintHelloNTimes(int n) 39 | { 40 | for(int i = 0; i < n; i++) 41 | { 42 | _printToConsole("Hello!"); 43 | } 44 | } 45 | } 46 | 47 | [TestFixture] 48 | public class EnthusiasticGreeterTests 49 | { 50 | private Mock> _printToConsoleMock; 51 | private EnthusiasticGreeter _cut; 52 | 53 | [SetUp] 54 | public void SetUp() 55 | { 56 | _printToConsoleMock = new Mock>(); 57 | _cut = new EnthusiasticGreeter( 58 | _printToConsoleMock.Object); 59 | } 60 | 61 | [Test] 62 | public void ShallPrintHello5Times_WhenCalledPrintHello5Times() 63 | { 64 | _cut.PrintHelloNTimes(5); 65 | _printToConsoleMock.Verify( 66 | mock => mock("Hello!"), Times.Exactly(5)); 67 | } 68 | } 69 | 70 | [TestFixture] 71 | public class PersonalDataFormatterTests 72 | { 73 | private Mock _peopleDataReaderMock; 74 | private PersonalDataFormatter _cut; 75 | 76 | [SetUp] 77 | public void SetUp() 78 | { 79 | _peopleDataReaderMock = new Mock(); 80 | _cut = new PersonalDataFormatter( 81 | _peopleDataReaderMock.Object); 82 | } 83 | 84 | [Test] 85 | public void ShallFormatPersonalDataCorrectly() 86 | { 87 | _peopleDataReaderMock.Setup(mock => mock.ReadPeople()) 88 | .Returns(new List 89 | { 90 | new Person("Person1", 1982, "Country1"), 91 | new Person("Person2", 1992, "Country2"), 92 | new Person("Person3", 1954, "Country3"), 93 | }); 94 | 95 | var result = _cut.Format(); 96 | var expectedResult = @"Person1 born in Country1 on 1982 97 | Person2 born in Country2 on 1992 98 | Person3 born in Country3 on 1954"; 99 | Assert.AreEqual(expectedResult, result); 100 | } 101 | } 102 | 103 | class PersonalDataFormatter 104 | { 105 | private readonly IPeopleDataReader _peopleDataReader; 106 | 107 | public PersonalDataFormatter( 108 | IPeopleDataReader peopleDataReader) 109 | { 110 | _peopleDataReader = peopleDataReader; 111 | } 112 | 113 | public string Format() 114 | { 115 | var people = _peopleDataReader.ReadPeople(); 116 | return string.Join(Environment.NewLine, 117 | people.Select(p => $"{p.Name} born in" + 118 | $" {p.Country} on {p.YearOfBirth}")); 119 | } 120 | } 121 | 122 | public interface IPeopleDataReader 123 | { 124 | IEnumerable ReadPeople(); 125 | } 126 | 127 | public class DatabasePeopleDataReader : IPeopleDataReader 128 | { 129 | public IEnumerable ReadPeople() 130 | { 131 | Console.WriteLine("Reading from real database"); 132 | return new List 133 | { 134 | new Person("John", 1982, "USA"), 135 | new Person("Aja", 1992, "India"), 136 | new Person("Tom", 1954, "Australia"), 137 | }; 138 | } 139 | } 140 | 141 | public record Person(string Name, int YearOfBirth, string Country); 142 | } -------------------------------------------------------------------------------- /DecoratorPattern/Program.cs: -------------------------------------------------------------------------------- 1 | Console.WriteLine("Both logging and count limiting"); 2 | 3 | IPeopleDataReader loggingCountLimitingPeopleDataReader = 4 | new CountLimitingDecorator(3, 5 | new LoggingDecorator(new Logger(), 6 | new PeopleDataReader())); 7 | 8 | //the order of Decorators matters! The below will give different result 9 | 10 | //IPeopleDataReader loggingCountLimitingPeopleDataReader = 11 | // new LoggingDecorator(new Logger(), 12 | // new CountLimitingDecorator(3, 13 | // new PeopleDataReader())); 14 | 15 | var people1 = loggingCountLimitingPeopleDataReader.Read(); 16 | foreach(var person in people1) 17 | { 18 | Console.WriteLine(person); 19 | } 20 | 21 | Console.WriteLine(); 22 | 23 | Console.WriteLine("Only count limiting"); 24 | 25 | IPeopleDataReader countLimitingPeopleDataReader = 26 | new CountLimitingDecorator(3, 27 | new PeopleDataReader()); 28 | 29 | var people2 = countLimitingPeopleDataReader.Read(); 30 | foreach (var person in people2) 31 | { 32 | Console.WriteLine(person); 33 | } 34 | 35 | Console.WriteLine(); 36 | 37 | Console.WriteLine("Only logging"); 38 | 39 | IPeopleDataReader loggingPeopleDataReader = 40 | new LoggingDecorator(new Logger(), 41 | new PeopleDataReader()); 42 | 43 | var people3 = loggingPeopleDataReader.Read(); 44 | foreach (var person in people3) 45 | { 46 | Console.WriteLine(person); 47 | } 48 | 49 | Console.ReadKey(); 50 | 51 | interface IPeopleDataReader 52 | { 53 | IEnumerable Read(); 54 | } 55 | 56 | class PeopleDataReader : IPeopleDataReader 57 | { 58 | public IEnumerable Read() 59 | { 60 | return new List 61 | { 62 | new Person("Martin", 1972, "France"), 63 | new Person("Aiko", 1995, "Japan"), 64 | new Person("Selene", 1944, "Great Britain"), 65 | new Person("Michael", 1980, "Canada"), 66 | new Person("Anne", 1974, "New Zealand"), 67 | }; 68 | } 69 | } 70 | 71 | class LoggingDecorator : IPeopleDataReader 72 | { 73 | private readonly IPeopleDataReader _decoratedReader; 74 | private readonly ILogger _log; 75 | 76 | public LoggingDecorator( 77 | ILogger log, 78 | IPeopleDataReader decoratedReader) 79 | { 80 | _decoratedReader = decoratedReader; 81 | _log = log; 82 | } 83 | 84 | public IEnumerable Read() 85 | { 86 | var data = _decoratedReader.Read(); 87 | _log.Log($"Read {data.Count()} elements"); 88 | return data; 89 | } 90 | } 91 | 92 | class CountLimitingDecorator : IPeopleDataReader 93 | { 94 | private readonly IPeopleDataReader _decoratedReader; 95 | private readonly int _countLimit; 96 | 97 | public CountLimitingDecorator( 98 | int countLimit, 99 | IPeopleDataReader decoratedReader) 100 | { 101 | _decoratedReader = decoratedReader; 102 | _countLimit = countLimit; 103 | } 104 | 105 | public IEnumerable Read() 106 | { 107 | Console.WriteLine( 108 | $"LIMITING the result to {_countLimit} elements"); 109 | return _decoratedReader.Read().Take(_countLimit); 110 | } 111 | } 112 | 113 | record Person(string FirstName, int YearOfBirth, string Country); 114 | 115 | interface ILogger 116 | { 117 | void Log(string message); 118 | } 119 | 120 | class Logger : ILogger 121 | { 122 | public void Log(string message) 123 | { 124 | Console.WriteLine($"[LOG] {message}"); 125 | } 126 | } 127 | 128 | class PeopleDataReaderWithoutDecorators: IPeopleDataReader 129 | { 130 | bool _shallLog; 131 | bool _shallLimitCount; 132 | int _countLimit; 133 | private readonly ILogger _log; 134 | 135 | public PeopleDataReaderWithoutDecorators( 136 | bool shallLog, 137 | bool shallLimitCount, 138 | ILogger log, 139 | int countLimit = 0) 140 | { 141 | _shallLog = shallLog; 142 | _log = log; 143 | _shallLimitCount = shallLimitCount; 144 | _countLimit = countLimit; 145 | } 146 | 147 | public IEnumerable Read() 148 | { 149 | var data = new List 150 | { 151 | new Person("Martin", 1972, "France"), 152 | new Person("Aiko", 1995, "Japan"), 153 | new Person("Selene", 1944, "Great Britain"), 154 | new Person("Michael", 1980, "Canada"), 155 | new Person("Anne", 1974, "New Zealand"), 156 | }; 157 | if (_shallLog) 158 | { 159 | _log.Log($"Read {data.Count()} elements"); 160 | } 161 | 162 | return _shallLimitCount ? 163 | data.Take(_countLimit) : 164 | data; 165 | } 166 | } -------------------------------------------------------------------------------- /InversionOfControl_WinFormsApp/HelloForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace InversionOfControl_WinFormsApp 2 | { 3 | partial class HelloForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.HelloLabel = new System.Windows.Forms.Label(); 32 | this.NameTextBox = new System.Windows.Forms.TextBox(); 33 | this.YearOfBirthTextBox = new System.Windows.Forms.TextBox(); 34 | this.YearOfBirthLabel = new System.Windows.Forms.Label(); 35 | this.button1 = new System.Windows.Forms.Button(); 36 | this.ResultTextBox = new System.Windows.Forms.Label(); 37 | this.SuspendLayout(); 38 | // 39 | // HelloLabel 40 | // 41 | this.HelloLabel.AutoSize = true; 42 | this.HelloLabel.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 43 | this.HelloLabel.Location = new System.Drawing.Point(100, 9); 44 | this.HelloLabel.Name = "HelloLabel"; 45 | this.HelloLabel.Size = new System.Drawing.Size(320, 37); 46 | this.HelloLabel.TabIndex = 0; 47 | this.HelloLabel.Text = "Hello! What\'s your name?"; 48 | // 49 | // NameTextBox 50 | // 51 | this.NameTextBox.Font = new System.Drawing.Font("Segoe UI", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 52 | this.NameTextBox.Location = new System.Drawing.Point(100, 59); 53 | this.NameTextBox.Name = "NameTextBox"; 54 | this.NameTextBox.PlaceholderText = "Type your name..."; 55 | this.NameTextBox.Size = new System.Drawing.Size(320, 43); 56 | this.NameTextBox.TabIndex = 1; 57 | this.NameTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.NameTextBox_KeyPress); 58 | // 59 | // YearOfBirthTextBox 60 | // 61 | this.YearOfBirthTextBox.Font = new System.Drawing.Font("Segoe UI", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 62 | this.YearOfBirthTextBox.Location = new System.Drawing.Point(100, 174); 63 | this.YearOfBirthTextBox.Name = "YearOfBirthTextBox"; 64 | this.YearOfBirthTextBox.PlaceholderText = "Type your year of birth..."; 65 | this.YearOfBirthTextBox.Size = new System.Drawing.Size(320, 43); 66 | this.YearOfBirthTextBox.TabIndex = 3; 67 | this.YearOfBirthTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.YearOfBirthTextBox_KeyPress); 68 | // 69 | // YearOfBirthLabel 70 | // 71 | this.YearOfBirthLabel.AutoSize = true; 72 | this.YearOfBirthLabel.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 73 | this.YearOfBirthLabel.Location = new System.Drawing.Point(100, 124); 74 | this.YearOfBirthLabel.Name = "YearOfBirthLabel"; 75 | this.YearOfBirthLabel.Size = new System.Drawing.Size(327, 37); 76 | this.YearOfBirthLabel.TabIndex = 2; 77 | this.YearOfBirthLabel.Text = "What year you were born?"; 78 | // 79 | // button1 80 | // 81 | this.button1.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 82 | this.button1.Location = new System.Drawing.Point(189, 223); 83 | this.button1.Name = "button1"; 84 | this.button1.Size = new System.Drawing.Size(119, 50); 85 | this.button1.TabIndex = 4; 86 | this.button1.Text = "Submit"; 87 | this.button1.UseVisualStyleBackColor = true; 88 | this.button1.Click += new System.EventHandler(this.SubmitButton_Click); 89 | // 90 | // ResultTextBox 91 | // 92 | this.ResultTextBox.AutoSize = true; 93 | this.ResultTextBox.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 94 | this.ResultTextBox.Location = new System.Drawing.Point(12, 276); 95 | this.ResultTextBox.Name = "ResultTextBox"; 96 | this.ResultTextBox.Size = new System.Drawing.Size(0, 37); 97 | this.ResultTextBox.TabIndex = 5; 98 | // 99 | // Form1 100 | // 101 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 102 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 103 | this.ClientSize = new System.Drawing.Size(507, 339); 104 | this.Controls.Add(this.ResultTextBox); 105 | this.Controls.Add(this.button1); 106 | this.Controls.Add(this.YearOfBirthTextBox); 107 | this.Controls.Add(this.YearOfBirthLabel); 108 | this.Controls.Add(this.NameTextBox); 109 | this.Controls.Add(this.HelloLabel); 110 | this.Name = "Form1"; 111 | this.Text = "Form1"; 112 | this.ResumeLayout(false); 113 | this.PerformLayout(); 114 | 115 | } 116 | 117 | #endregion 118 | 119 | private Label HelloLabel; 120 | private TextBox NameTextBox; 121 | private TextBox YearOfBirthTextBox; 122 | private Label YearOfBirthLabel; 123 | private Button button1; 124 | private Label ResultTextBox; 125 | } 126 | } -------------------------------------------------------------------------------- /50InterviewQuestionsMid.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31912.275 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsVsAs", "IsVsAs\IsVsAs.csproj", "{F21709E5-F002-49DE-885C-87C53EDF24CB}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PatternMatching", "PatternMatching\PatternMatching.csproj", "{F8AE36D3-C5B1-4784-8DEC-077416A09BC9}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UsingKeyword", "UsingKeyword\UsingKeyword.csproj", "{9623A002-2AFB-4701-B00D-12E1BB07F362}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CheckedKeyword", "CheckedKeyword\CheckedKeyword.csproj", "{E212615C-1F7E-4021-B6D5-31E30A333371}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Record", "Record\Record.csproj", "{BD088F44-1F74-4D67-91B7-5D65D14E02C7}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Indexers", "Indexers\Indexers.csproj", "{0587DED4-479A-49D5-856B-8FAEDD24D19A}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OperatorOverloading", "OperatorOverloading\OperatorOverloading.csproj", "{D5F6EC21-7D70-443C-8CFB-88AC47AA015D}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExpressionBodiedMembers", "ExpressionBodiedMembers\ExpressionBodiedMembers.csproj", "{67E6B5A7-43F3-45E4-ABD3-FE3954224757}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Caching", "Caching\Caching.csproj", "{C6E0431D-6AB4-4783-B4EC-060A437F2B1F}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NullableReferenceTypes", "NullableReferenceTypes\NullableReferenceTypes.csproj", "{7F4B1010-6EBC-41F6-8ECD-123B6BB91243}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImmutableTypes", "ImmutableTypes\ImmutableTypes.csproj", "{DBBAF693-5F61-4C16-8B3E-D10C457CC336}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnonymousTypes", "AnonymousTypes\AnonymousTypes.csproj", "{FDA797D4-7791-4D17-A443-DD729B180D4B}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CheckedPerformanceTest", "CheckedPerformanceTest\CheckedPerformanceTest.csproj", "{766133BB-B03C-4D5D-8F35-084347ACC456}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DoubleVsDecimal", "DoubleVsDecimal\DoubleVsDecimal.csproj", "{6AAB7643-B402-4835-9E6A-AF0548313A57}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DoubleVsDecimalPerformanceTest", "DoubleVsDecimalPerformanceTest\DoubleVsDecimalPerformanceTest.csproj", "{F3D2B5A4-F5FF-4144-83B7-54342FF6C094}" 35 | EndProject 36 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThrowVsThrowEx", "ThrowVsThrowEx\ThrowVsThrowEx.csproj", "{01672C9C-4474-4B0E-ABB4-2E79406D8F09}" 37 | EndProject 38 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StringVsStringBuilder", "StringVsStringBuilder\StringVsStringBuilder.csproj", "{16F72F01-8BEA-43A2-B452-8952FAACCB90}" 39 | EndProject 40 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StringVsStringBuilderPerformanceTest", "StringVsStringBuilderPerformanceTest\StringVsStringBuilderPerformanceTest.csproj", "{0F0A1F30-F1F2-4343-94EC-C873F8FAD723}" 41 | EndProject 42 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TupleVsValueTuple", "TupleVsValueTuple\TupleVsValueTuple.csproj", "{E8568377-6E38-4C35-8A54-004E3E2E41F7}" 43 | EndProject 44 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Attributes", "Attributes\Attributes.csproj", "{37462469-FDD1-4D2D-A545-CC7D94F55562}" 45 | EndProject 46 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Reflection", "Reflection\Reflection.csproj", "{F97AA6BE-FBF0-42C1-979C-563C6C59B242}" 47 | EndProject 48 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DefaultInterfaceImplementation", "DefaultInterfaceImplementation\DefaultInterfaceImplementation.csproj", "{93A53072-F22B-4927-A640-C70538EACE6A}" 49 | EndProject 50 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisposeVsFinalize", "FinalizeVsDispose\DisposeVsFinalize.csproj", "{8E0F0745-766C-4BA6-AEB5-BBA99243A033}" 51 | EndProject 52 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cohesion", "Cohesion\Cohesion.csproj", "{C1300058-E7F5-4755-AD03-454CA7B86006}" 53 | EndProject 54 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Coupling", "Coupling\Coupling.csproj", "{73581720-4DB1-4A96-B60B-B178D2D0721A}" 55 | EndProject 56 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollectionsArray", "CollectionsArray\CollectionsArray.csproj", "{C9329B8B-15C2-4FD1-996B-1F20136ECDF5}" 57 | EndProject 58 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollectionsLists", "CollectionsLists\CollectionsLists.csproj", "{A1855FC6-490E-4A9C-B28E-436A67651F54}" 59 | EndProject 60 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollectionsArrayLists", "CollectionsArrayLists\CollectionsArrayLists.csproj", "{8525AFB6-87DB-400C-AA29-F32BF67CE930}" 61 | EndProject 62 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollectionsDictionary", "CollectionsDictionary\CollectionsDictionary.csproj", "{DED1E155-9B65-4D38-811B-1A7A6210BD3A}" 63 | EndProject 64 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetHashCode", "GetHashCode\GetHashCode.csproj", "{A48626E9-AD08-4B92-B0C8-53797A6FCBA7}" 65 | EndProject 66 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Deconstruction", "Deconstruction\Deconstruction.csproj", "{3425A978-53AD-4ACC-9180-564CCA6D2D52}" 67 | EndProject 68 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicKeyword", "DynamicKeyword\DynamicKeyword.csproj", "{47AED28E-CE9D-485D-A738-E743D36A5A91}" 69 | EndProject 70 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Delegates", "Delegates\Delegates.csproj", "{F2682120-A6F8-44D0-B3D0-3F02A95A84E2}" 71 | EndProject 72 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObserverDesignPattern", "ObserverDesignPattern\ObserverDesignPattern.csproj", "{DAC63A5A-17B9-4348-8DD6-A4AE55D0B415}" 73 | EndProject 74 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Events", "Events\Events.csproj", "{8AD356F6-743B-4D60-9E16-86C0A4C0F1DC}" 75 | EndProject 76 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NuGet", "NuGet\NuGet.csproj", "{4983B656-3BBA-4266-ADAC-D3A8C680C907}" 77 | EndProject 78 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GarbageCollectorAlgorithm", "GarbageCollectorAlgorithm\GarbageCollectorAlgorithm.csproj", "{A410833D-D800-438B-B0C4-78ABB3C39AFB}" 79 | EndProject 80 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompositionOverInheritance_Composition", "CompositionOverInheritance_Composition\CompositionOverInheritance_Composition.csproj", "{2207BA8C-DCD7-4DE1-B7CB-3C85A4EEEA78}" 81 | EndProject 82 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompositionOverInheritance_Inheritance", "CompositionOverInheritance_Inheritance\CompositionOverInheritance_Inheritance.csproj", "{F5485B51-8B7B-441B-9479-5EE24AFE5EFC}" 83 | EndProject 84 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompositionOverInheritance_GoodInheritance", "CompositionOverInheritance_GoodInheritance\CompositionOverInheritance_GoodInheritance.csproj", "{FAC2BBE4-BE3C-4454-B69B-B06641D57F91}" 85 | EndProject 86 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependencyInjection", "DependencyInjection\DependencyInjection.csproj", "{D035481F-A6A9-444C-B9A6-8ECA92F4A7D3}" 87 | EndProject 88 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InversionOfControl_ConsoleApp", "InversionOfControl_ConsoleApp\InversionOfControl_ConsoleApp.csproj", "{5D66FA50-DD9D-47EB-874F-44EBD14A92D4}" 89 | EndProject 90 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InversionOfControl_WinFormsApp", "InversionOfControl_WinFormsApp\InversionOfControl_WinFormsApp.csproj", "{28FEF1D8-F3BC-4464-B056-03088ABA6749}" 91 | EndProject 92 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InversionOfControl", "InversionOfControl\InversionOfControl.csproj", "{682A83A8-5441-47B7-B9E9-F73B43B0247B}" 93 | EndProject 94 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Strategy", "Strategy\Strategy.csproj", "{C4D43E1D-D745-454B-ADFB-86791D8750B0}" 95 | EndProject 96 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemplateMethod", "TemplateMethod\TemplateMethod.csproj", "{CB540063-B231-4BB5-AC77-C7FECEA3EBB4}" 97 | EndProject 98 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemplateMethod_UnitTests", "TemplateMethod_UnitTests\TemplateMethod_UnitTests.csproj", "{E5BD3FC6-B1B7-426C-95A5-8A2AFBDC4B83}" 99 | EndProject 100 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mocks", "Mocks\Mocks.csproj", "{8F834E6E-B3C0-458E-AE93-70A3A8D7C1B3}" 101 | EndProject 102 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DecoratorPattern", "DecoratorPattern\DecoratorPattern.csproj", "{65FD6B9C-5232-4BA5-A5B0-F99D11D835E9}" 103 | EndProject 104 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StringImmutability", "StringImmutability\StringImmutability.csproj", "{AF06C95B-6AFA-4389-A46D-62C1F43B6941}" 105 | EndProject 106 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CatchException", "CatchException\CatchException.csproj", "{A5ECB103-1CC8-4541-B3D0-B90AD0673E04}" 107 | EndProject 108 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TypeofVsGetType", "TypeofVsGetType\TypeofVsGetType.csproj", "{8D6074E7-5347-48A4-BC02-82162AA4E451}" 109 | EndProject 110 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DebugVsRelease", "DebugVsRelease\DebugVsRelease.csproj", "{B0D13CA9-0ECD-4E40-A19F-EAC6FD93340A}" 111 | EndProject 112 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PreprocessorDirectives", "PreprocessorDirectives\PreprocessorDirectives.csproj", "{E1A00F53-28DB-4917-9528-CF58EE60ACEC}" 113 | EndProject 114 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization", "Serialization\Serialization.csproj", "{450E2111-2AA3-4D9B-AAB6-4263DF242768}" 115 | EndProject 116 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuncsAndLambdaExpressions", "FuncsAndLambdaExpressions\FuncsAndLambdaExpressions.csproj", "{2D70AE29-B2BA-4E17-BEA9-15AC0257129F}" 117 | EndProject 118 | Global 119 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 120 | Debug|Any CPU = Debug|Any CPU 121 | Release|Any CPU = Release|Any CPU 122 | EndGlobalSection 123 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 124 | {F21709E5-F002-49DE-885C-87C53EDF24CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 125 | {F21709E5-F002-49DE-885C-87C53EDF24CB}.Debug|Any CPU.Build.0 = Debug|Any CPU 126 | {F21709E5-F002-49DE-885C-87C53EDF24CB}.Release|Any CPU.ActiveCfg = Release|Any CPU 127 | {F21709E5-F002-49DE-885C-87C53EDF24CB}.Release|Any CPU.Build.0 = Release|Any CPU 128 | {F8AE36D3-C5B1-4784-8DEC-077416A09BC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 129 | {F8AE36D3-C5B1-4784-8DEC-077416A09BC9}.Debug|Any CPU.Build.0 = Debug|Any CPU 130 | {F8AE36D3-C5B1-4784-8DEC-077416A09BC9}.Release|Any CPU.ActiveCfg = Release|Any CPU 131 | {F8AE36D3-C5B1-4784-8DEC-077416A09BC9}.Release|Any CPU.Build.0 = Release|Any CPU 132 | {9623A002-2AFB-4701-B00D-12E1BB07F362}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 133 | {9623A002-2AFB-4701-B00D-12E1BB07F362}.Debug|Any CPU.Build.0 = Debug|Any CPU 134 | {9623A002-2AFB-4701-B00D-12E1BB07F362}.Release|Any CPU.ActiveCfg = Release|Any CPU 135 | {9623A002-2AFB-4701-B00D-12E1BB07F362}.Release|Any CPU.Build.0 = Release|Any CPU 136 | {E212615C-1F7E-4021-B6D5-31E30A333371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 137 | {E212615C-1F7E-4021-B6D5-31E30A333371}.Debug|Any CPU.Build.0 = Debug|Any CPU 138 | {E212615C-1F7E-4021-B6D5-31E30A333371}.Release|Any CPU.ActiveCfg = Release|Any CPU 139 | {E212615C-1F7E-4021-B6D5-31E30A333371}.Release|Any CPU.Build.0 = Release|Any CPU 140 | {BD088F44-1F74-4D67-91B7-5D65D14E02C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 141 | {BD088F44-1F74-4D67-91B7-5D65D14E02C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 142 | {BD088F44-1F74-4D67-91B7-5D65D14E02C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 143 | {BD088F44-1F74-4D67-91B7-5D65D14E02C7}.Release|Any CPU.Build.0 = Release|Any CPU 144 | {0587DED4-479A-49D5-856B-8FAEDD24D19A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 145 | {0587DED4-479A-49D5-856B-8FAEDD24D19A}.Debug|Any CPU.Build.0 = Debug|Any CPU 146 | {0587DED4-479A-49D5-856B-8FAEDD24D19A}.Release|Any CPU.ActiveCfg = Release|Any CPU 147 | {0587DED4-479A-49D5-856B-8FAEDD24D19A}.Release|Any CPU.Build.0 = Release|Any CPU 148 | {D5F6EC21-7D70-443C-8CFB-88AC47AA015D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 149 | {D5F6EC21-7D70-443C-8CFB-88AC47AA015D}.Debug|Any CPU.Build.0 = Debug|Any CPU 150 | {D5F6EC21-7D70-443C-8CFB-88AC47AA015D}.Release|Any CPU.ActiveCfg = Release|Any CPU 151 | {D5F6EC21-7D70-443C-8CFB-88AC47AA015D}.Release|Any CPU.Build.0 = Release|Any CPU 152 | {67E6B5A7-43F3-45E4-ABD3-FE3954224757}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 153 | {67E6B5A7-43F3-45E4-ABD3-FE3954224757}.Debug|Any CPU.Build.0 = Debug|Any CPU 154 | {67E6B5A7-43F3-45E4-ABD3-FE3954224757}.Release|Any CPU.ActiveCfg = Release|Any CPU 155 | {67E6B5A7-43F3-45E4-ABD3-FE3954224757}.Release|Any CPU.Build.0 = Release|Any CPU 156 | {C6E0431D-6AB4-4783-B4EC-060A437F2B1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 157 | {C6E0431D-6AB4-4783-B4EC-060A437F2B1F}.Debug|Any CPU.Build.0 = Debug|Any CPU 158 | {C6E0431D-6AB4-4783-B4EC-060A437F2B1F}.Release|Any CPU.ActiveCfg = Release|Any CPU 159 | {C6E0431D-6AB4-4783-B4EC-060A437F2B1F}.Release|Any CPU.Build.0 = Release|Any CPU 160 | {7F4B1010-6EBC-41F6-8ECD-123B6BB91243}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 161 | {7F4B1010-6EBC-41F6-8ECD-123B6BB91243}.Debug|Any CPU.Build.0 = Debug|Any CPU 162 | {7F4B1010-6EBC-41F6-8ECD-123B6BB91243}.Release|Any CPU.ActiveCfg = Release|Any CPU 163 | {7F4B1010-6EBC-41F6-8ECD-123B6BB91243}.Release|Any CPU.Build.0 = Release|Any CPU 164 | {DBBAF693-5F61-4C16-8B3E-D10C457CC336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 165 | {DBBAF693-5F61-4C16-8B3E-D10C457CC336}.Debug|Any CPU.Build.0 = Debug|Any CPU 166 | {DBBAF693-5F61-4C16-8B3E-D10C457CC336}.Release|Any CPU.ActiveCfg = Release|Any CPU 167 | {DBBAF693-5F61-4C16-8B3E-D10C457CC336}.Release|Any CPU.Build.0 = Release|Any CPU 168 | {FDA797D4-7791-4D17-A443-DD729B180D4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 169 | {FDA797D4-7791-4D17-A443-DD729B180D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU 170 | {FDA797D4-7791-4D17-A443-DD729B180D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU 171 | {FDA797D4-7791-4D17-A443-DD729B180D4B}.Release|Any CPU.Build.0 = Release|Any CPU 172 | {766133BB-B03C-4D5D-8F35-084347ACC456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 173 | {766133BB-B03C-4D5D-8F35-084347ACC456}.Debug|Any CPU.Build.0 = Debug|Any CPU 174 | {766133BB-B03C-4D5D-8F35-084347ACC456}.Release|Any CPU.ActiveCfg = Release|Any CPU 175 | {766133BB-B03C-4D5D-8F35-084347ACC456}.Release|Any CPU.Build.0 = Release|Any CPU 176 | {6AAB7643-B402-4835-9E6A-AF0548313A57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 177 | {6AAB7643-B402-4835-9E6A-AF0548313A57}.Debug|Any CPU.Build.0 = Debug|Any CPU 178 | {6AAB7643-B402-4835-9E6A-AF0548313A57}.Release|Any CPU.ActiveCfg = Release|Any CPU 179 | {6AAB7643-B402-4835-9E6A-AF0548313A57}.Release|Any CPU.Build.0 = Release|Any CPU 180 | {F3D2B5A4-F5FF-4144-83B7-54342FF6C094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 181 | {F3D2B5A4-F5FF-4144-83B7-54342FF6C094}.Debug|Any CPU.Build.0 = Debug|Any CPU 182 | {F3D2B5A4-F5FF-4144-83B7-54342FF6C094}.Release|Any CPU.ActiveCfg = Release|Any CPU 183 | {F3D2B5A4-F5FF-4144-83B7-54342FF6C094}.Release|Any CPU.Build.0 = Release|Any CPU 184 | {01672C9C-4474-4B0E-ABB4-2E79406D8F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 185 | {01672C9C-4474-4B0E-ABB4-2E79406D8F09}.Debug|Any CPU.Build.0 = Debug|Any CPU 186 | {01672C9C-4474-4B0E-ABB4-2E79406D8F09}.Release|Any CPU.ActiveCfg = Release|Any CPU 187 | {01672C9C-4474-4B0E-ABB4-2E79406D8F09}.Release|Any CPU.Build.0 = Release|Any CPU 188 | {16F72F01-8BEA-43A2-B452-8952FAACCB90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 189 | {16F72F01-8BEA-43A2-B452-8952FAACCB90}.Debug|Any CPU.Build.0 = Debug|Any CPU 190 | {16F72F01-8BEA-43A2-B452-8952FAACCB90}.Release|Any CPU.ActiveCfg = Release|Any CPU 191 | {16F72F01-8BEA-43A2-B452-8952FAACCB90}.Release|Any CPU.Build.0 = Release|Any CPU 192 | {0F0A1F30-F1F2-4343-94EC-C873F8FAD723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 193 | {0F0A1F30-F1F2-4343-94EC-C873F8FAD723}.Debug|Any CPU.Build.0 = Debug|Any CPU 194 | {0F0A1F30-F1F2-4343-94EC-C873F8FAD723}.Release|Any CPU.ActiveCfg = Release|Any CPU 195 | {0F0A1F30-F1F2-4343-94EC-C873F8FAD723}.Release|Any CPU.Build.0 = Release|Any CPU 196 | {E8568377-6E38-4C35-8A54-004E3E2E41F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 197 | {E8568377-6E38-4C35-8A54-004E3E2E41F7}.Debug|Any CPU.Build.0 = Debug|Any CPU 198 | {E8568377-6E38-4C35-8A54-004E3E2E41F7}.Release|Any CPU.ActiveCfg = Release|Any CPU 199 | {E8568377-6E38-4C35-8A54-004E3E2E41F7}.Release|Any CPU.Build.0 = Release|Any CPU 200 | {37462469-FDD1-4D2D-A545-CC7D94F55562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 201 | {37462469-FDD1-4D2D-A545-CC7D94F55562}.Debug|Any CPU.Build.0 = Debug|Any CPU 202 | {37462469-FDD1-4D2D-A545-CC7D94F55562}.Release|Any CPU.ActiveCfg = Release|Any CPU 203 | {37462469-FDD1-4D2D-A545-CC7D94F55562}.Release|Any CPU.Build.0 = Release|Any CPU 204 | {F97AA6BE-FBF0-42C1-979C-563C6C59B242}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 205 | {F97AA6BE-FBF0-42C1-979C-563C6C59B242}.Debug|Any CPU.Build.0 = Debug|Any CPU 206 | {F97AA6BE-FBF0-42C1-979C-563C6C59B242}.Release|Any CPU.ActiveCfg = Release|Any CPU 207 | {F97AA6BE-FBF0-42C1-979C-563C6C59B242}.Release|Any CPU.Build.0 = Release|Any CPU 208 | {93A53072-F22B-4927-A640-C70538EACE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 209 | {93A53072-F22B-4927-A640-C70538EACE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU 210 | {93A53072-F22B-4927-A640-C70538EACE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU 211 | {93A53072-F22B-4927-A640-C70538EACE6A}.Release|Any CPU.Build.0 = Release|Any CPU 212 | {8E0F0745-766C-4BA6-AEB5-BBA99243A033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 213 | {8E0F0745-766C-4BA6-AEB5-BBA99243A033}.Debug|Any CPU.Build.0 = Debug|Any CPU 214 | {8E0F0745-766C-4BA6-AEB5-BBA99243A033}.Release|Any CPU.ActiveCfg = Release|Any CPU 215 | {8E0F0745-766C-4BA6-AEB5-BBA99243A033}.Release|Any CPU.Build.0 = Release|Any CPU 216 | {C1300058-E7F5-4755-AD03-454CA7B86006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 217 | {C1300058-E7F5-4755-AD03-454CA7B86006}.Debug|Any CPU.Build.0 = Debug|Any CPU 218 | {C1300058-E7F5-4755-AD03-454CA7B86006}.Release|Any CPU.ActiveCfg = Release|Any CPU 219 | {C1300058-E7F5-4755-AD03-454CA7B86006}.Release|Any CPU.Build.0 = Release|Any CPU 220 | {73581720-4DB1-4A96-B60B-B178D2D0721A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 221 | {73581720-4DB1-4A96-B60B-B178D2D0721A}.Debug|Any CPU.Build.0 = Debug|Any CPU 222 | {73581720-4DB1-4A96-B60B-B178D2D0721A}.Release|Any CPU.ActiveCfg = Release|Any CPU 223 | {73581720-4DB1-4A96-B60B-B178D2D0721A}.Release|Any CPU.Build.0 = Release|Any CPU 224 | {C9329B8B-15C2-4FD1-996B-1F20136ECDF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 225 | {C9329B8B-15C2-4FD1-996B-1F20136ECDF5}.Debug|Any CPU.Build.0 = Debug|Any CPU 226 | {C9329B8B-15C2-4FD1-996B-1F20136ECDF5}.Release|Any CPU.ActiveCfg = Release|Any CPU 227 | {C9329B8B-15C2-4FD1-996B-1F20136ECDF5}.Release|Any CPU.Build.0 = Release|Any CPU 228 | {A1855FC6-490E-4A9C-B28E-436A67651F54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 229 | {A1855FC6-490E-4A9C-B28E-436A67651F54}.Debug|Any CPU.Build.0 = Debug|Any CPU 230 | {A1855FC6-490E-4A9C-B28E-436A67651F54}.Release|Any CPU.ActiveCfg = Release|Any CPU 231 | {A1855FC6-490E-4A9C-B28E-436A67651F54}.Release|Any CPU.Build.0 = Release|Any CPU 232 | {8525AFB6-87DB-400C-AA29-F32BF67CE930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 233 | {8525AFB6-87DB-400C-AA29-F32BF67CE930}.Debug|Any CPU.Build.0 = Debug|Any CPU 234 | {8525AFB6-87DB-400C-AA29-F32BF67CE930}.Release|Any CPU.ActiveCfg = Release|Any CPU 235 | {8525AFB6-87DB-400C-AA29-F32BF67CE930}.Release|Any CPU.Build.0 = Release|Any CPU 236 | {DED1E155-9B65-4D38-811B-1A7A6210BD3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 237 | {DED1E155-9B65-4D38-811B-1A7A6210BD3A}.Debug|Any CPU.Build.0 = Debug|Any CPU 238 | {DED1E155-9B65-4D38-811B-1A7A6210BD3A}.Release|Any CPU.ActiveCfg = Release|Any CPU 239 | {DED1E155-9B65-4D38-811B-1A7A6210BD3A}.Release|Any CPU.Build.0 = Release|Any CPU 240 | {A48626E9-AD08-4B92-B0C8-53797A6FCBA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 241 | {A48626E9-AD08-4B92-B0C8-53797A6FCBA7}.Debug|Any CPU.Build.0 = Debug|Any CPU 242 | {A48626E9-AD08-4B92-B0C8-53797A6FCBA7}.Release|Any CPU.ActiveCfg = Release|Any CPU 243 | {A48626E9-AD08-4B92-B0C8-53797A6FCBA7}.Release|Any CPU.Build.0 = Release|Any CPU 244 | {3425A978-53AD-4ACC-9180-564CCA6D2D52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 245 | {3425A978-53AD-4ACC-9180-564CCA6D2D52}.Debug|Any CPU.Build.0 = Debug|Any CPU 246 | {3425A978-53AD-4ACC-9180-564CCA6D2D52}.Release|Any CPU.ActiveCfg = Release|Any CPU 247 | {3425A978-53AD-4ACC-9180-564CCA6D2D52}.Release|Any CPU.Build.0 = Release|Any CPU 248 | {47AED28E-CE9D-485D-A738-E743D36A5A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 249 | {47AED28E-CE9D-485D-A738-E743D36A5A91}.Debug|Any CPU.Build.0 = Debug|Any CPU 250 | {47AED28E-CE9D-485D-A738-E743D36A5A91}.Release|Any CPU.ActiveCfg = Release|Any CPU 251 | {47AED28E-CE9D-485D-A738-E743D36A5A91}.Release|Any CPU.Build.0 = Release|Any CPU 252 | {F2682120-A6F8-44D0-B3D0-3F02A95A84E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 253 | {F2682120-A6F8-44D0-B3D0-3F02A95A84E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 254 | {F2682120-A6F8-44D0-B3D0-3F02A95A84E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 255 | {F2682120-A6F8-44D0-B3D0-3F02A95A84E2}.Release|Any CPU.Build.0 = Release|Any CPU 256 | {DAC63A5A-17B9-4348-8DD6-A4AE55D0B415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 257 | {DAC63A5A-17B9-4348-8DD6-A4AE55D0B415}.Debug|Any CPU.Build.0 = Debug|Any CPU 258 | {DAC63A5A-17B9-4348-8DD6-A4AE55D0B415}.Release|Any CPU.ActiveCfg = Release|Any CPU 259 | {DAC63A5A-17B9-4348-8DD6-A4AE55D0B415}.Release|Any CPU.Build.0 = Release|Any CPU 260 | {8AD356F6-743B-4D60-9E16-86C0A4C0F1DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 261 | {8AD356F6-743B-4D60-9E16-86C0A4C0F1DC}.Debug|Any CPU.Build.0 = Debug|Any CPU 262 | {8AD356F6-743B-4D60-9E16-86C0A4C0F1DC}.Release|Any CPU.ActiveCfg = Release|Any CPU 263 | {8AD356F6-743B-4D60-9E16-86C0A4C0F1DC}.Release|Any CPU.Build.0 = Release|Any CPU 264 | {4983B656-3BBA-4266-ADAC-D3A8C680C907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 265 | {4983B656-3BBA-4266-ADAC-D3A8C680C907}.Debug|Any CPU.Build.0 = Debug|Any CPU 266 | {4983B656-3BBA-4266-ADAC-D3A8C680C907}.Release|Any CPU.ActiveCfg = Release|Any CPU 267 | {4983B656-3BBA-4266-ADAC-D3A8C680C907}.Release|Any CPU.Build.0 = Release|Any CPU 268 | {A410833D-D800-438B-B0C4-78ABB3C39AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 269 | {A410833D-D800-438B-B0C4-78ABB3C39AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU 270 | {A410833D-D800-438B-B0C4-78ABB3C39AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU 271 | {A410833D-D800-438B-B0C4-78ABB3C39AFB}.Release|Any CPU.Build.0 = Release|Any CPU 272 | {2207BA8C-DCD7-4DE1-B7CB-3C85A4EEEA78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 273 | {2207BA8C-DCD7-4DE1-B7CB-3C85A4EEEA78}.Debug|Any CPU.Build.0 = Debug|Any CPU 274 | {2207BA8C-DCD7-4DE1-B7CB-3C85A4EEEA78}.Release|Any CPU.ActiveCfg = Release|Any CPU 275 | {2207BA8C-DCD7-4DE1-B7CB-3C85A4EEEA78}.Release|Any CPU.Build.0 = Release|Any CPU 276 | {F5485B51-8B7B-441B-9479-5EE24AFE5EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 277 | {F5485B51-8B7B-441B-9479-5EE24AFE5EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU 278 | {F5485B51-8B7B-441B-9479-5EE24AFE5EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU 279 | {F5485B51-8B7B-441B-9479-5EE24AFE5EFC}.Release|Any CPU.Build.0 = Release|Any CPU 280 | {FAC2BBE4-BE3C-4454-B69B-B06641D57F91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 281 | {FAC2BBE4-BE3C-4454-B69B-B06641D57F91}.Debug|Any CPU.Build.0 = Debug|Any CPU 282 | {FAC2BBE4-BE3C-4454-B69B-B06641D57F91}.Release|Any CPU.ActiveCfg = Release|Any CPU 283 | {FAC2BBE4-BE3C-4454-B69B-B06641D57F91}.Release|Any CPU.Build.0 = Release|Any CPU 284 | {D035481F-A6A9-444C-B9A6-8ECA92F4A7D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 285 | {D035481F-A6A9-444C-B9A6-8ECA92F4A7D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 286 | {D035481F-A6A9-444C-B9A6-8ECA92F4A7D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 287 | {D035481F-A6A9-444C-B9A6-8ECA92F4A7D3}.Release|Any CPU.Build.0 = Release|Any CPU 288 | {5D66FA50-DD9D-47EB-874F-44EBD14A92D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 289 | {5D66FA50-DD9D-47EB-874F-44EBD14A92D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 290 | {5D66FA50-DD9D-47EB-874F-44EBD14A92D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 291 | {5D66FA50-DD9D-47EB-874F-44EBD14A92D4}.Release|Any CPU.Build.0 = Release|Any CPU 292 | {28FEF1D8-F3BC-4464-B056-03088ABA6749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 293 | {28FEF1D8-F3BC-4464-B056-03088ABA6749}.Debug|Any CPU.Build.0 = Debug|Any CPU 294 | {28FEF1D8-F3BC-4464-B056-03088ABA6749}.Release|Any CPU.ActiveCfg = Release|Any CPU 295 | {28FEF1D8-F3BC-4464-B056-03088ABA6749}.Release|Any CPU.Build.0 = Release|Any CPU 296 | {682A83A8-5441-47B7-B9E9-F73B43B0247B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 297 | {682A83A8-5441-47B7-B9E9-F73B43B0247B}.Debug|Any CPU.Build.0 = Debug|Any CPU 298 | {682A83A8-5441-47B7-B9E9-F73B43B0247B}.Release|Any CPU.ActiveCfg = Release|Any CPU 299 | {682A83A8-5441-47B7-B9E9-F73B43B0247B}.Release|Any CPU.Build.0 = Release|Any CPU 300 | {C4D43E1D-D745-454B-ADFB-86791D8750B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 301 | {C4D43E1D-D745-454B-ADFB-86791D8750B0}.Debug|Any CPU.Build.0 = Debug|Any CPU 302 | {C4D43E1D-D745-454B-ADFB-86791D8750B0}.Release|Any CPU.ActiveCfg = Release|Any CPU 303 | {C4D43E1D-D745-454B-ADFB-86791D8750B0}.Release|Any CPU.Build.0 = Release|Any CPU 304 | {CB540063-B231-4BB5-AC77-C7FECEA3EBB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 305 | {CB540063-B231-4BB5-AC77-C7FECEA3EBB4}.Debug|Any CPU.Build.0 = Debug|Any CPU 306 | {CB540063-B231-4BB5-AC77-C7FECEA3EBB4}.Release|Any CPU.ActiveCfg = Release|Any CPU 307 | {CB540063-B231-4BB5-AC77-C7FECEA3EBB4}.Release|Any CPU.Build.0 = Release|Any CPU 308 | {E5BD3FC6-B1B7-426C-95A5-8A2AFBDC4B83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 309 | {E5BD3FC6-B1B7-426C-95A5-8A2AFBDC4B83}.Debug|Any CPU.Build.0 = Debug|Any CPU 310 | {E5BD3FC6-B1B7-426C-95A5-8A2AFBDC4B83}.Release|Any CPU.ActiveCfg = Release|Any CPU 311 | {E5BD3FC6-B1B7-426C-95A5-8A2AFBDC4B83}.Release|Any CPU.Build.0 = Release|Any CPU 312 | {8F834E6E-B3C0-458E-AE93-70A3A8D7C1B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 313 | {8F834E6E-B3C0-458E-AE93-70A3A8D7C1B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 314 | {8F834E6E-B3C0-458E-AE93-70A3A8D7C1B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 315 | {8F834E6E-B3C0-458E-AE93-70A3A8D7C1B3}.Release|Any CPU.Build.0 = Release|Any CPU 316 | {65FD6B9C-5232-4BA5-A5B0-F99D11D835E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 317 | {65FD6B9C-5232-4BA5-A5B0-F99D11D835E9}.Debug|Any CPU.Build.0 = Debug|Any CPU 318 | {65FD6B9C-5232-4BA5-A5B0-F99D11D835E9}.Release|Any CPU.ActiveCfg = Release|Any CPU 319 | {65FD6B9C-5232-4BA5-A5B0-F99D11D835E9}.Release|Any CPU.Build.0 = Release|Any CPU 320 | {AF06C95B-6AFA-4389-A46D-62C1F43B6941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 321 | {AF06C95B-6AFA-4389-A46D-62C1F43B6941}.Debug|Any CPU.Build.0 = Debug|Any CPU 322 | {AF06C95B-6AFA-4389-A46D-62C1F43B6941}.Release|Any CPU.ActiveCfg = Release|Any CPU 323 | {AF06C95B-6AFA-4389-A46D-62C1F43B6941}.Release|Any CPU.Build.0 = Release|Any CPU 324 | {A5ECB103-1CC8-4541-B3D0-B90AD0673E04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 325 | {A5ECB103-1CC8-4541-B3D0-B90AD0673E04}.Debug|Any CPU.Build.0 = Debug|Any CPU 326 | {A5ECB103-1CC8-4541-B3D0-B90AD0673E04}.Release|Any CPU.ActiveCfg = Release|Any CPU 327 | {A5ECB103-1CC8-4541-B3D0-B90AD0673E04}.Release|Any CPU.Build.0 = Release|Any CPU 328 | {8D6074E7-5347-48A4-BC02-82162AA4E451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 329 | {8D6074E7-5347-48A4-BC02-82162AA4E451}.Debug|Any CPU.Build.0 = Debug|Any CPU 330 | {8D6074E7-5347-48A4-BC02-82162AA4E451}.Release|Any CPU.ActiveCfg = Release|Any CPU 331 | {8D6074E7-5347-48A4-BC02-82162AA4E451}.Release|Any CPU.Build.0 = Release|Any CPU 332 | {B0D13CA9-0ECD-4E40-A19F-EAC6FD93340A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 333 | {B0D13CA9-0ECD-4E40-A19F-EAC6FD93340A}.Debug|Any CPU.Build.0 = Debug|Any CPU 334 | {B0D13CA9-0ECD-4E40-A19F-EAC6FD93340A}.Release|Any CPU.ActiveCfg = Release|Any CPU 335 | {B0D13CA9-0ECD-4E40-A19F-EAC6FD93340A}.Release|Any CPU.Build.0 = Release|Any CPU 336 | {E1A00F53-28DB-4917-9528-CF58EE60ACEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 337 | {E1A00F53-28DB-4917-9528-CF58EE60ACEC}.Debug|Any CPU.Build.0 = Debug|Any CPU 338 | {E1A00F53-28DB-4917-9528-CF58EE60ACEC}.Release|Any CPU.ActiveCfg = Release|Any CPU 339 | {E1A00F53-28DB-4917-9528-CF58EE60ACEC}.Release|Any CPU.Build.0 = Release|Any CPU 340 | {450E2111-2AA3-4D9B-AAB6-4263DF242768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 341 | {450E2111-2AA3-4D9B-AAB6-4263DF242768}.Debug|Any CPU.Build.0 = Debug|Any CPU 342 | {450E2111-2AA3-4D9B-AAB6-4263DF242768}.Release|Any CPU.ActiveCfg = Release|Any CPU 343 | {450E2111-2AA3-4D9B-AAB6-4263DF242768}.Release|Any CPU.Build.0 = Release|Any CPU 344 | {2D70AE29-B2BA-4E17-BEA9-15AC0257129F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 345 | {2D70AE29-B2BA-4E17-BEA9-15AC0257129F}.Debug|Any CPU.Build.0 = Debug|Any CPU 346 | {2D70AE29-B2BA-4E17-BEA9-15AC0257129F}.Release|Any CPU.ActiveCfg = Release|Any CPU 347 | {2D70AE29-B2BA-4E17-BEA9-15AC0257129F}.Release|Any CPU.Build.0 = Release|Any CPU 348 | EndGlobalSection 349 | GlobalSection(SolutionProperties) = preSolution 350 | HideSolutionNode = FALSE 351 | EndGlobalSection 352 | GlobalSection(ExtensibilityGlobals) = postSolution 353 | SolutionGuid = {E21AF45E-E0DB-4BB4-83E8-AE8CF9ED1588} 354 | EndGlobalSection 355 | EndGlobal 356 | --------------------------------------------------------------------------------