├── Chapter09 ├── packages.config ├── App.config ├── Program.cs ├── NameofWithAlias.cs ├── HorribleCode.cs ├── GlobalSuppressions.cs ├── Chapter09.csproj ├── FormatPriceInterpolatedVerbatim.cs ├── EagerEvaluation.cs ├── FormatPrice.cs ├── FormatPriceInterpolated.cs ├── SimpleNameof.cs ├── QualifiedNameof.cs ├── BirthdayInAllCultures.cs ├── FormatDateInvariant.cs ├── SqlInjection.cs └── LazyEvaluation.cs ├── Chapter10 ├── packages.config ├── App.config ├── Program.cs ├── Person.cs ├── CombineEnums.cs ├── UsingStaticExtensionMethods2.cs ├── Chapter10.csproj ├── Point.cs ├── CoordinatesOldStyle.cs ├── CoordinatesUsingStatic.cs ├── UsingStaticExtensionMethods1.cs ├── DictionaryInitialization.cs ├── ObjectInitializerIndexer.cs ├── LoggingFilter.cs ├── SpecializedAddExtensionMethod.cs ├── CollectionInitializerExtensionMethods.cs ├── FirstExceptionFilter.cs ├── AddRangeAsAdd.cs ├── SwitchOnEnum.cs ├── ConcurrentDictionaryCollectionInitializer.cs └── SimpleRetry.cs ├── CSharp8 ├── Chapter15 │ ├── Program.cs │ ├── Chapter15.csproj │ ├── DamnItOperator.cs │ ├── BrokenInitialExample.cs │ ├── GeoServiceDemo.cs │ ├── IGeoService.cs │ ├── NullableAddressFix1.cs │ ├── EverythingNonNullable.cs │ ├── GeoClient.cs │ ├── NullableAddressFix3.cs │ ├── NullableAddressFix2.cs │ ├── AsyncDisposal.cs │ ├── NullableAddress.cs │ ├── DeconstructionPattern.cs │ ├── PropertyPatterns1.cs │ ├── SwitchExpressionBodiedMember.cs │ ├── SwitchExpression.cs │ └── DamnItOperatorValidation.cs └── README.md ├── Chapter11 ├── App.config ├── packages.config ├── Program.cs ├── Chapter11.csproj ├── InferredTupleElementNames.cs ├── ElementAccess.cs ├── Indexing.cs ├── FibonacciWithTuples.cs ├── EqualityOperators.cs ├── RegularComparisons.cs ├── FibonacciWithoutTuples.cs ├── Game.cs ├── StructuralComparisons.cs ├── FibonacciWithGenerator.cs ├── HighScoreDisplayWithTuples.cs ├── HighScoreDisplayWithoutTuples.cs ├── MinMax3.cs ├── MinMax1.cs └── MinMax2.cs ├── Chapter04Com ├── App.config ├── Program.cs ├── SaveFileNew.cs ├── ExcelDynamic.cs ├── NamedIndexers.cs └── SaveFileOld.cs ├── Chapter09Net40 ├── App.config ├── Chapter09Net40.csproj ├── Program.cs ├── FormattableStringFactory.cs └── FormattableString.cs ├── Chapter02 ├── Program.cs ├── Chapter02.csproj ├── IteratorBlockWithFinallyDemo1.cs ├── TypeOfExample.cs ├── IteratorBlockWithFinallyDemo3.cs ├── FixedBuffers.cs ├── FixedBuffersInFields.cs ├── NullableBoxing.cs ├── NullableGetType.cs ├── PartialDemo1.cs ├── SimpleIterator.cs ├── TypeConstraints.cs ├── IteratorBlockWithFinally.cs ├── StaticClasses.cs ├── NamesWithArray.cs ├── IteratorBlockWithFinallyDemo2.cs ├── NamesWithArrayList.cs ├── FibonacciSequence.cs ├── GenericMethod.cs ├── NamesWithList.cs ├── LineReader.cs ├── NamesWithStringCollection.cs ├── ExpandedForEach.cs ├── GenericCounter.cs ├── DecompilationExampleOriginal.cs └── PartialDemo2.cs ├── Chapter05 ├── Program.cs ├── AsyncEntryPoint.cs ├── Chapter05.csproj ├── ManuallyInducedCancellation.cs ├── AsyncLambda.cs ├── AwaitCompletedTask.cs ├── PrintPageLength.cs ├── LazyArgumentValidation.cs ├── UnsafeCodeInAsyncMethod.cs ├── EagerArgumentValidation1.cs ├── AwaitingFailedOperations.cs ├── AsyncIntro.cs ├── EagerArgumentValidation2.cs └── EagerArgumentValidation3.cs ├── Chapter06 ├── Program.cs ├── Chapter06.csproj ├── SimpleAsyncMethod.cs ├── AwaitInsideLoop.cs ├── AsyncMethodWithSimpleLoop.cs └── AwaitInsideTryFinally.cs ├── Chapter12 ├── Program.cs ├── TupleLiteralDeconstruction.cs ├── Chapter12.csproj ├── TupleDeconstructionExplicitTyping.cs ├── TupleDeconstructionEvaluationOrdering.cs ├── DateTimeDeconstruction.cs ├── TupleDeconstructionOverview.cs ├── TupleDeconstructionAssignments.cs ├── Point.cs ├── TupleDeconstructionEvaluationOrderingExplained.cs ├── ConstantPatterns.cs ├── TypePatternWithNullableType.cs ├── FizzBuzz.cs ├── FibonacciSwitch.cs ├── DateTimeDeconstruction2.cs ├── NumericBounds.cs ├── ShapePerimeterWithPatternsIfElse.cs ├── GenericTypeCase.cs ├── Shape.cs ├── ShapePerimeterWithPatternsSwitchCase.cs └── ShapePerimeterBeforePatterns.cs ├── Chapter13 ├── Program.cs ├── StackAllocWithInitializer.cs ├── Vector3D.cs ├── RefReassignment.cs ├── RefLocalIntro.cs ├── RefReturnNoLocal.cs ├── NoParameterCopy.cs ├── Vector3DExtensions.cs ├── RefLocalIdentityConversions.cs ├── Chapter13.csproj ├── RefReturnSimpleNoLocal.cs ├── RefReadonly.cs ├── RefReturnSimple.cs ├── InParameterOverloading.cs ├── RefParameterRecap.cs ├── ImplicitFieldCopy.cs ├── UsingVector3DExtensions.cs ├── RefLocalField.cs ├── LargeStruct.cs ├── RefReturnIndexer.cs ├── FixedSpan.cs ├── ImplicitParameterCopy.cs ├── RefLocalArrays.cs ├── InParameterOptions.cs ├── ReadOnlyArrayView.cs ├── YearMonthDay.cs ├── GenerateRandomString1.cs ├── GenerateRandomString3.cs ├── RefConditional.cs ├── GenerateRandomString2.cs ├── ReadonlyStructUnsafeViolation.cs ├── InParameterSideEffects.cs ├── GenerateRandomString4.cs └── SafeInParameters.cs ├── Chapter14 ├── Program.cs ├── Preconditions.cs ├── FieldAttributes.cs ├── NonTrailingNamedArguments.cs ├── DefaultExpression1.cs ├── LocalMethodInLoop.cs ├── DefaultLiteralOptionalParameter.cs ├── LocalMethodVariableCapture1.cs ├── Chapter14.csproj ├── DefaultExpression2.cs ├── ExplicitListDefaultValue.cs ├── LocalMethodIntro.cs ├── LocalMethodVariableCapture3.cs ├── LocalMethodVariableCapture2.cs ├── LocalMethodVariableCapture1Equivalent.cs ├── LocalMethodVariableCapture3Equivalent.cs ├── GenericConstraints.cs ├── SelectBeforeLocalMethods.cs ├── SelectWithLocalMethods.cs ├── LocalMethodVariableCapture2Equivalent.cs ├── LocalMethodUsingThisInStruct.cs ├── OutVarInConstructorInitializer.cs └── OverloadResolution.cs ├── Chapter03 ├── Program.cs ├── ExtensionMethodInvocation.cs ├── ExpressionTreeIntro.cs ├── Chapter03.csproj ├── ExpressionTreeCompilation.cs ├── AnonymousTypeIntro.cs ├── NestedObjectInitializer.cs ├── ExtensionMethodChaining.cs ├── QueryWithLocalVariables.cs ├── QueryExpression1.cs ├── NestedMethodCalls.cs ├── ExpressionTreeIntroImpl.cs ├── QueryExpression2Impl.cs ├── QueryExpression2.cs ├── CapturingMultipleInstantiations.cs ├── CapturingMultipleInstantiationsImpl.cs ├── CapturingMultipleScopes.cs └── CapturedVariablesDemo.cs ├── Chapter04 ├── Program.cs ├── Chapter04.csproj ├── DynamicAddition.cs ├── DynamicTypingIntro.cs ├── LinqCovariance.cs ├── LinqWithoutVariance.cs ├── DynamicAnonymousTypes.cs ├── InvalidCalls.cs ├── OptionalParameterIntro.cs ├── DynamicTypingAndExplicitInterfaceImplementation.cs ├── InvalidLinqQuery.cs ├── DynamicLinqQuery.cs ├── DynamicJsonParsing.cs ├── DynamicLinqQueryWithQueryable.cs ├── ExpandoObjectIntroduction.cs ├── DyanamicOverloadResolution.cs ├── SimpleDynamicExample.cs └── MixedDynamicAndStaticOverloadResolution.cs ├── Chapter07 ├── Program.cs ├── Chapter07.csproj ├── CallerInfoDemo.cs ├── ForEachCapture.cs ├── ForLoopCapture.cs ├── DynamicAndCallerInfo.cs ├── CallerInfoConstructors.cs ├── OldPropertyNotifier.cs └── NewPropertyNotifier.cs └── Chapter08 ├── Person.cs ├── Chapter08.csproj ├── Vector.cs ├── PointStruct.cs ├── ReadOnlyListView.cs └── Point.cs /Chapter09/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter15 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) => ApplicationChooser.Run(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter09/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Chapter10/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Chapter11/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Chapter04Com/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter09Net40/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter02/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter02 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter05/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter05 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter06/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter06 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter12/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter12 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter13/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter13 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter14/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter14 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter11/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Chapter03/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter03 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter04/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter04 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter10/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter10 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter04Com/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter04Com 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter09/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter09 4 | { 5 | public class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter11/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | 3 | namespace Chapter11 4 | { 5 | public class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | ApplicationChooser.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/Program.cs: -------------------------------------------------------------------------------- 1 | using JonSkeet.DemoUtil; 2 | using System; 3 | 4 | namespace Chapter07 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | ApplicationChooser.Run(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter08/Person.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter08 5 | { 6 | [Description("Listing 8.10")] 7 | public class Person 8 | { 9 | public List Friends { get; } = new List(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter08/Chapter08.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter14/Preconditions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | static class Preconditions 6 | { 7 | internal static T CheckNotNull(T value, string paramName) where T : class 8 | => value ?? throw new ArgumentNullException(paramName); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter09Net40/Chapter09Net40.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net40 6 | Chapter09Net40.Program 7 | 8 | -------------------------------------------------------------------------------- /Chapter08/Vector.cs: -------------------------------------------------------------------------------- 1 | namespace Chapter08 2 | { 3 | public sealed class Vector 4 | { 5 | public double X { get; } 6 | public double Y { get; } 7 | 8 | public Vector(double x, double y) 9 | { 10 | X = x; 11 | Y = y; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter10/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Chapter10 6 | { 7 | class Person 8 | { 9 | public string Name { get; set; } 10 | public string Town { get; set; } 11 | public List Contacts { get; } = new List(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter13/StackAllocWithInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class StackAllocWithInitializer 6 | { 7 | unsafe static void Main() 8 | { 9 | Span span = stackalloc int[] { 1, 2, 3 }; 10 | int* pointer = stackalloc int[] { 4, 5, 6 }; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/NameofWithAlias.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using GuidAlias = System.Guid; 4 | 5 | namespace Chapter09 6 | { 7 | [Description("Listing 9.17")] 8 | class NameofWithAlias 9 | { 10 | static void Main() 11 | { 12 | Console.WriteLine(nameof(GuidAlias)); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/CombineEnums.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | using static System.Reflection.BindingFlags; 4 | 5 | namespace Chapter10 6 | { 7 | class CombineEnums 8 | { 9 | static void Main() 10 | { 11 | var fields = typeof(CombineEnums).GetFields(Instance | Static | Public | NonPublic); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter07/Chapter07.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | Chapter07.Program 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter13/Vector3D.cs: -------------------------------------------------------------------------------- 1 | namespace Chapter13 2 | { 3 | public readonly struct Vector3D 4 | { 5 | public double X { get; } 6 | public double Y { get; } 7 | public double Z { get; } 8 | 9 | public Vector3D(double x, double y, double z) 10 | { 11 | X = x; 12 | Y = y; 13 | Z = z; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter08/PointStruct.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter08 4 | { 5 | [Description("Listing 8.12")] 6 | public struct PointStruct 7 | { 8 | public double X { get; } 9 | public double Y { get; } 10 | 11 | public PointStruct(double x, double y) 12 | { 13 | X = x; 14 | Y = y; 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/ExtensionMethodInvocation.cs: -------------------------------------------------------------------------------- 1 | using NodaTime.Extensions; 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace CSharpInDepth.Chapter03 6 | { 7 | [Description("Listing 3.16")] 8 | class ExtensionMethodInvocation 9 | { 10 | static void Main() 11 | { 12 | var currentInstant = DateTimeOffset.UtcNow.ToInstant(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter13/RefReassignment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class RefReassignment 6 | { 7 | static void Main() 8 | { 9 | int x = 10; 10 | int y = 20; 11 | ref int r = ref x; 12 | r++; 13 | r = ref y; 14 | r++; 15 | Console.WriteLine($"x={x}; y={y}"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter14/FieldAttributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | [AttributeUsage(AttributeTargets.Field)] 6 | class DemoAttribute : Attribute 7 | { 8 | } 9 | 10 | class FieldAttributes 11 | { 12 | [field: Demo] 13 | public static int Value { get; set; } 14 | 15 | [field: Demo] 16 | public static event EventHandler Foo; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter13/RefLocalIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.2")] 7 | public class RefLocalIntro 8 | { 9 | static void Main() 10 | { 11 | int x = 10; 12 | ref int y = ref x; 13 | x++; 14 | y++; 15 | Console.WriteLine(x); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter09/HorribleCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter09 4 | { 5 | class HorribleCode 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine($@"Hello {((Func)(() => 10 | { 11 | Console.Write("What's your name? "); 12 | return Console.ReadLine(); 13 | }))()}!"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter09Net40/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter09Net40 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | int value = 5; 10 | FormattableString formattable = $"value={value}"; 11 | Console.WriteLine(formattable.Format); 12 | Console.WriteLine(formattable.GetArgument(0)); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter14/NonTrailingNamedArguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | class NonTrailingNamedArguments 6 | { 7 | static void Method(int x, int y = 5, int z = 10) 8 | { 9 | Console.WriteLine("x={0}; y={1}; z={2}", x, y, z); 10 | } 11 | 12 | static void Main() 13 | { 14 | Method(x: 1, y: 2, 3); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter09/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | 2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | [assembly: SuppressMessage("Style", "IDE0030", Justification = "Introduced in chapter 8")] -------------------------------------------------------------------------------- /Chapter14/DefaultExpression1.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Chapter14 5 | { 6 | class DefaultExpression1 7 | { 8 | public async Task FetchValueAsync(string key, CancellationToken cancellationToken = default) 9 | { 10 | await Task.Delay(1000, cancellationToken); 11 | return "irrelevant"; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter12/TupleLiteralDeconstruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Snippet in section 10.1.3")] 7 | class TupleLiteralDeconstruction 8 | { 9 | static void Main() 10 | { 11 | (string text, Func func) = (null, x => x * 2); 12 | (text, func) = ("text", x => x * 3); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter03/ExpressionTreeIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | 5 | namespace Chapter03 6 | { 7 | [Description("Listing 3.12")] 8 | class ExpressionTreeIntro 9 | { 10 | static void Main() 11 | { 12 | Expression> adder = (x, y) => x + y; 13 | Console.WriteLine(adder); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter09Net40/FormattableStringFactory.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace System.Runtime.CompilerServices 4 | { 5 | [Description("Listing 9.10 (first half)")] 6 | internal static class FormattableStringFactory 7 | { 8 | internal static FormattableString Create( 9 | string format, params object[] arguments) => 10 | new FormattableString(format, arguments); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter03/Chapter03.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | Chapter03.Program 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter09/Chapter09.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net462 5 | Chapter09.Program 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodInLoop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | class LocalMethodInLoop 6 | { 7 | static void Main() 8 | { 9 | for (int i = 0; i < 10; i++) 10 | { 11 | PrintI(); 12 | 13 | void PrintI() 14 | { 15 | Console.WriteLine(i); 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter05/AsyncEntryPoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.11")] 8 | class AsyncEntryPoint 9 | { 10 | static async Task Main() 11 | { 12 | Console.WriteLine("Before delay"); 13 | await Task.Delay(1000); 14 | Console.WriteLine("After delay"); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter13/RefReturnNoLocal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class RefReturnAsRefArgument 6 | { 7 | static void Main() 8 | { 9 | int x = 10; 10 | RefReturn(ref RefReturn(ref RefReturn(ref x)))++; 11 | Console.WriteLine(x); 12 | } 13 | 14 | static ref int RefReturn(ref int p) 15 | { 16 | return ref p; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter04/Chapter04.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | Chapter04.Program 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter13/NoParameterCopy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter13 6 | { 7 | class NoParameterCopy 8 | { 9 | public void PrintYearMonthDay(YearMonthDay input) 10 | { 11 | int year = input.Year; 12 | int month = input.Month; 13 | int day = input.Day; 14 | Console.WriteLine($"{year} {month} {day}"); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter14/DefaultLiteralOptionalParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | [Description("Listing 14.11")] 7 | class DefaultLiteralOptionalParameter 8 | { 9 | static void PrintValue(int value = 10) 10 | { 11 | Console.WriteLine(value); 12 | } 13 | 14 | static void Main() 15 | { 16 | PrintValue(default); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter13/Vector3DExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | public static class Vector3DExtensions 6 | { 7 | public static double Magnitude(this in Vector3D vec) => 8 | Math.Sqrt(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z); 9 | 10 | public static void OffsetBy(this ref Vector3D orig, in Vector3D off) => 11 | orig = new Vector3D(orig.X + off.X, orig.Y + off.Y, orig.Z + off.Z); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | [Description("Listing 14.2")] 7 | class LocalMethodVariableCapture1 8 | { 9 | static void Main() 10 | { 11 | int i = 0; 12 | AddToI(5); 13 | AddToI(10); 14 | Console.WriteLine(i); 15 | void AddToI(int amount) => i += amount; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter02/Chapter02.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | Chapter02.Program 6 | 7.3 7 | True 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter13/RefLocalIdentityConversions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.5")] 7 | class RefLocalIdentityConversions 8 | { 9 | static void Main() 10 | { 11 | (int x, int y) tuple1 = (10, 20); 12 | ref (int a, int b) tuple2 = ref tuple1; 13 | tuple2.a = 30; 14 | Console.WriteLine(tuple1.x); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter02/IteratorBlockWithFinallyDemo1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.15")] 7 | class IteratorBlockWithFinallyDemo1 8 | { 9 | static void Main() 10 | { 11 | foreach (string value in IteratorBlockWithFinally.Iterator()) 12 | { 13 | Console.WriteLine("Received value: {0}", value); 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter04/DynamicAddition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04 5 | { 6 | [Description("Listing 4.2")] 7 | class DynamicAddition 8 | { 9 | static void Add(dynamic d) 10 | { 11 | Console.WriteLine(d + d); 12 | } 13 | 14 | static void Main() 15 | { 16 | Add("text"); 17 | Add(10); 18 | Add(TimeSpan.FromMinutes(45)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter13/Chapter13.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | Chapter13.Program 7 | latest 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter11/Chapter11.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | Chapter11.Program 7 | latest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter13/RefReturnSimpleNoLocal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.7")] 7 | class RefReturnSimpleNoLocal 8 | { 9 | static void Main() 10 | { 11 | int x = 10; 12 | RefReturn(ref x)++; 13 | Console.WriteLine(x); 14 | } 15 | 16 | static ref int RefReturn(ref int p) 17 | { 18 | return ref p; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter14/Chapter14.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | Chapter14.Program 7 | 7.3 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter04/DynamicTypingIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04 5 | { 6 | [Description("Listing 4.1")] 7 | class DynamicTypingIntro 8 | { 9 | static void Main() 10 | { 11 | dynamic text = "hello world"; 12 | string world = text.Substring(6); 13 | Console.WriteLine(world); 14 | 15 | string broken = text.SUBSTR(6); 16 | Console.WriteLine(broken); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter12/Chapter12.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | Chapter12.Program 7 | latest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter09/FormatPriceInterpolatedVerbatim.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter09 5 | { 6 | [Description("Listing 9.4")] 7 | public class FormatPriceInterpolatedVerbatim 8 | { 9 | static void Main() 10 | { 11 | decimal price = 95.25m; 12 | decimal tip = price * 0.2m; 13 | Console.WriteLine($@"Price: {price,9:C} 14 | Tip: {tip,9:C} 15 | Total: {price + tip,9:C}"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter13/RefReadonly.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.10")] 7 | class RefReadonly 8 | { 9 | private static readonly int field = DateTime.UtcNow.Second; 10 | 11 | static ref readonly int GetFieldAlias() => ref field; 12 | 13 | static void Main() 14 | { 15 | ref readonly int local = ref GetFieldAlias(); 16 | Console.WriteLine(local); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter04/LinqCovariance.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | 5 | namespace Chapter04 6 | { 7 | [Description("Listing 4.20")] 8 | class LinqCovariance 9 | { 10 | static void Main() 11 | { 12 | IEnumerable strings = new[] { "a", "b", "cdefg", "hij" }; 13 | List list = strings 14 | .Where(x => x.Length > 1) 15 | .ToList(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter09/EagerEvaluation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter09 5 | { 6 | [Description("Listing 9.11")] 7 | class EagerEvaluation 8 | { 9 | static void Main() 10 | { 11 | string value = "Before"; 12 | FormattableString formattable = $"Current value: {value}"; 13 | Console.WriteLine(formattable); 14 | 15 | value = "After"; 16 | Console.WriteLine(formattable); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter13/RefReturnSimple.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.6")] 7 | class RefReturnSimple 8 | { 9 | static void Main() 10 | { 11 | int x = 10; 12 | ref int y = ref RefReturn(ref x); 13 | y++; 14 | Console.WriteLine(x); 15 | } 16 | 17 | static ref int RefReturn(ref int p) 18 | { 19 | return ref p; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter10/UsingStaticExtensionMethods2.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using static System.Linq.Enumerable; 4 | 5 | namespace Chapter10 6 | { 7 | [Description("Listing 10.4")] 8 | class UsingStaticExtensionMethods2 9 | { 10 | static void Main() 11 | { 12 | IEnumerable strings = new[] { "a", "b", "c" }; 13 | 14 | int valid = strings.Count(); 15 | // int invalid = Count(strings); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter13/InParameterOverloading.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class InParameterOverloading 6 | { 7 | static void Method(int x) => 8 | Console.WriteLine("Value parameter"); 9 | 10 | static void Method(in int x) => 11 | Console.WriteLine("In parameter"); 12 | 13 | static void Main() 14 | { 15 | int x = 5; 16 | Method(5); 17 | Method(x); 18 | Method(in x); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter03/ExpressionTreeCompilation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | 5 | namespace Chapter03 6 | { 7 | [Description("Listing 3.14")] 8 | class ExpressionTreeCompilation 9 | { 10 | static void Main() 11 | { 12 | Expression> adder = (x, y) => x + y; 13 | Func executableAdder = adder.Compile(); 14 | Console.WriteLine(executableAdder(2, 3)); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter12/TupleDeconstructionExplicitTyping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.2")] 7 | class TupleDeconstructionExplicitTyping 8 | { 9 | static (int x, int y, string text) MethodReturningTuple() => (1, 2, "t"); 10 | 11 | static void Main() 12 | { 13 | (int a, int b, string name) = MethodReturningTuple(); 14 | Console.WriteLine($"a: {a}; b: {b}; name: {name}"); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter14/DefaultExpression2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | class DefaultExpression2 6 | { 7 | static void Main() 8 | { 9 | var intArray = new[] { default, 5 }; 10 | var stringArray = new[] { default, "text" }; 11 | var boolArray = new[] { default, true }; 12 | 13 | Console.WriteLine(intArray[0]); 14 | Console.WriteLine(stringArray[0] == null); 15 | Console.WriteLine(boolArray[0]); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter10/Chapter10.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | Chapter10.Program 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter13/RefParameterRecap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.1")] 7 | class RefParameterRecap 8 | { 9 | static void Main() 10 | { 11 | int x = 5; 12 | IncrementAndDouble(ref x, ref x); 13 | Console.WriteLine(x); 14 | } 15 | 16 | static void IncrementAndDouble(ref int p1, ref int p2) 17 | { 18 | p1++; 19 | p2 *= 2; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter09/FormatPrice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter09 5 | { 6 | [Description("Listing 9.1")] 7 | public class FormatPrice 8 | { 9 | static void Main() 10 | { 11 | decimal price = 95.25m; 12 | decimal tip = price * 0.2m; // 20% tip 13 | Console.WriteLine("Price: {0,9:C}", price); 14 | Console.WriteLine("Tip: {0,9:C}", tip); 15 | Console.WriteLine("Total: {0,9:C}", price + tip); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/AnonymousTypeIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter03 5 | { 6 | [Description("Listing 3.5")] 7 | class AnonymousTypeIntro 8 | { 9 | static void Main() 10 | { 11 | var player = new 12 | { 13 | Name = "Tony", 14 | Score = 3500 15 | }; 16 | Console.WriteLine("Player name: {0}", player.Name); 17 | Console.WriteLine("Player score: {0}", player.Score); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter09/FormatPriceInterpolated.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter09 5 | { 6 | [Description("Listing 9.4")] 7 | public class FormatPriceInterpolated 8 | { 9 | static void Main() 10 | { 11 | decimal price = 95.25m; 12 | decimal tip = price * 0.2m; 13 | Console.WriteLine($"Price: {price,9:C}"); 14 | Console.WriteLine($"Tip: {tip,9:C}"); 15 | Console.WriteLine($"Total: {price + tip,9:C}"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter13/ImplicitFieldCopy.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter13 4 | { 5 | [Description("Listing 13.16")] 6 | class ImplicitFieldCopy 7 | { 8 | private readonly YearMonthDay readOnlyField = new YearMonthDay(2018, 3, 1); 9 | private YearMonthDay readWriteField = new YearMonthDay(2018, 3, 1); 10 | 11 | public void CheckYear() 12 | { 13 | int readOnlyFieldYear = readOnlyField.Year; 14 | int readWriteFieldYear = readWriteField.Year; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter04/LinqWithoutVariance.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | 5 | namespace Chapter04 6 | { 7 | [Description("Listing 4.19")] 8 | class LinqWithoutVariance 9 | { 10 | static void Main() 11 | { 12 | IEnumerable strings = new[] { "a", "b", "cdefg", "hij" }; 13 | List list = strings 14 | .Where(x => x.Length > 1) 15 | .Cast() 16 | .ToList(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter11/InferredTupleElementNames.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Chapter11 6 | { 7 | class InferredTupleElementNames 8 | { 9 | static void Main() 10 | { 11 | List list = new List { 5, 1, -6, 2 }; 12 | var tuple = (list.Count, Min: list.Min(), Max: list.Max()); 13 | Console.WriteLine(tuple.Count); 14 | Console.WriteLine(tuple.Min); 15 | Console.WriteLine(tuple.Max); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter09/SimpleNameof.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | #pragma warning disable CS0649 5 | 6 | namespace Chapter09 7 | { 8 | [Description("Listing 9.12")] 9 | class SimpleNameof 10 | { 11 | private string field; 12 | 13 | static void Main(string[] args) 14 | { 15 | Console.WriteLine(nameof(SimpleNameof)); 16 | Console.WriteLine(nameof(Main)); 17 | Console.WriteLine(nameof(args)); 18 | Console.WriteLine(nameof(field)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/Chapter15.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | Chapter15.Program 7 | 8.0 8 | enable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter06/Chapter06.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | Chapter06.Program 6 | 7.1 7 | True 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter10/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chapter10 8 | { 9 | // TODO: Implement equality, ToString etc. 10 | public struct Point 11 | { 12 | public double X { get; } 13 | public double Y { get; } 14 | 15 | public Point(double x, double y) 16 | { 17 | X = x; 18 | Y = y; 19 | } 20 | 21 | public override String ToString() => $"({X}, {Y})"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter11/ElementAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter11 5 | { 6 | [Description("Listing 11.2")] 7 | class ElementAccess 8 | { 9 | static void Main() 10 | { 11 | var tuple = (x: 5, 10); 12 | Console.WriteLine(tuple.x); 13 | Console.WriteLine(tuple.Item1); 14 | Console.WriteLine(tuple.Item2); 15 | 16 | tuple.x = 100; 17 | Console.WriteLine(tuple.Item1); // Prints 100 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter04/DynamicAnonymousTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04 5 | { 6 | [Description("Listing 4.12")] 7 | class DynamicAnonymousTypes 8 | { 9 | static void PrintName(dynamic obj) 10 | { 11 | Console.WriteLine(obj.Name); 12 | } 13 | 14 | static void Main() 15 | { 16 | var x = new { Name = "Abc" }; 17 | var y = new { Name = "Def", Score = 10 }; 18 | PrintName(x); 19 | PrintName(y); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter04/InvalidCalls.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter04 4 | { 5 | [Description("Listing 4.4")] 6 | class InvalidCalls 7 | { 8 | static void Main() 9 | { 10 | /* All these calls are invalid 11 | dynamic d = new object(); 12 | int invalid1 = "text".Substring(0, 1, 2, d); 13 | bool invalid2 = string.Equals("foo", d); 14 | string invalid3 = new string(d, "broken"); 15 | char invalid4 = "text"[d, d]; 16 | */ 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter02/TypeOfExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 2.7")] 8 | class TypeOfExample 9 | { 10 | static void PrintType() 11 | { 12 | Console.WriteLine("typeof(T) = {0}", typeof(T)); 13 | Console.WriteLine("typeof(List) = {0}", typeof(List)); 14 | } 15 | 16 | static void Main() 17 | { 18 | PrintType(); 19 | PrintType(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter13/UsingVector3DExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.19")] 7 | class UsingVector3DExtensions 8 | { 9 | static void Main() 10 | { 11 | var vector = new Vector3D(1.5, 2.0, 3.0); 12 | var offset = new Vector3D(5.0, 2.5, -1.0); 13 | 14 | vector.OffsetBy(offset); 15 | 16 | Console.WriteLine($"({vector.X}, {vector.Y}, {vector.Z})"); 17 | Console.WriteLine(vector.Magnitude()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter03/NestedObjectInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Net.Http; 4 | 5 | namespace Chapter03 6 | { 7 | [Description("Listing 3.4")] 8 | class NestedObjectInitializer 9 | { 10 | static void Main() 11 | { 12 | HttpClient client = new HttpClient 13 | { 14 | DefaultRequestHeaders = 15 | { 16 | From = "user@example.com", 17 | Date = DateTimeOffset.UtcNow 18 | } 19 | }; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter02/IteratorBlockWithFinallyDemo3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.16")] 7 | class IteratorBlockWithFinallyDemo2 8 | { 9 | static void Main() 10 | { 11 | foreach (string value in IteratorBlockWithFinally.Iterator()) 12 | { 13 | Console.WriteLine("Received value: {0}", value); 14 | if (value != null) 15 | { 16 | break; 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter13/RefLocalField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.4")] 7 | class RefLocalField 8 | { 9 | private int value; 10 | 11 | static void Main() 12 | { 13 | var obj = new RefLocalField(); 14 | ref int tmp = ref obj.value; 15 | tmp = 10; 16 | Console.WriteLine(obj.value); 17 | 18 | obj = new RefLocalField(); 19 | Console.WriteLine(tmp); 20 | Console.WriteLine(obj.value); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter02/FixedBuffers.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter02 4 | { 5 | [Description("Listing 2.26")] 6 | class FixedBuffers 7 | { 8 | unsafe struct VersionedData 9 | { 10 | public int Major; 11 | public int Minor; 12 | public fixed byte Data[16]; 13 | } 14 | 15 | unsafe static void Main() 16 | { 17 | var versioned = new VersionedData(); 18 | versioned.Major = 2; 19 | versioned.Minor = 1; 20 | versioned.Data[10] = 20; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter02/FixedBuffersInFields.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter02 4 | { 5 | class FixedBuffersInFields 6 | { 7 | unsafe struct VersionedData 8 | { 9 | public int Major; 10 | public int Minor; 11 | public fixed byte Data[16]; 12 | } 13 | 14 | static VersionedData field; 15 | 16 | unsafe static void Main() 17 | { 18 | field = new VersionedData(); 19 | field.Major = 2; 20 | field.Minor = 1; 21 | field.Data[10] = 20; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter02/NullableBoxing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.9")] 7 | class NullableBoxing 8 | { 9 | static void Main() 10 | { 11 | Nullable noValue = new Nullable(); 12 | object noValueBoxed = noValue; 13 | Console.WriteLine(noValueBoxed == null); 14 | 15 | Nullable someValue = new Nullable(5); 16 | object someValueBoxed = someValue; 17 | Console.WriteLine(someValueBoxed.GetType()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter12/TupleDeconstructionEvaluationOrdering.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Text; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.5")] 8 | class TupleDeconstructionEvaluationOrdering 9 | { 10 | static void Main() 11 | { 12 | StringBuilder builder = new StringBuilder("12345"); 13 | StringBuilder original = builder; 14 | 15 | (builder, builder.Length) = (new StringBuilder("67890"), 3); 16 | 17 | Console.WriteLine(original); 18 | Console.WriteLine(builder); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter10/CoordinatesOldStyle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter10 5 | { 6 | [Description("Listing 10.1")] 7 | class CoordinatesOldStyle 8 | { 9 | static void Main() 10 | { 11 | Console.WriteLine(PolarToCartesian(60, 20)); 12 | } 13 | 14 | static Point PolarToCartesian(double degrees, double magnitude) 15 | { 16 | double radians = degrees * Math.PI / 180; 17 | return new Point( 18 | Math.Cos(radians) * magnitude, 19 | Math.Sin(radians) * magnitude); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter11/Indexing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Chapter11 6 | { 7 | static class Indexing 8 | { 9 | static void Main() 10 | { 11 | string[] array = { "first", "second", "third" }; 12 | foreach (var pair in array.WithIndex()) 13 | { 14 | Console.WriteLine(pair); 15 | } 16 | } 17 | 18 | static IEnumerable<(T value, int index)> WithIndex 19 | (this IEnumerable source) => 20 | source.Select((value, index) => (value, index)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter14/ExplicitListDefaultValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter14 6 | { 7 | class ExplicitListDefaultValue 8 | { 9 | static void Main() 10 | { 11 | var list = new List { 5, 2, 1 }; 12 | Console.WriteLine(GetValueOrDefault(list, 1)); 13 | Console.WriteLine(GetValueOrDefault(list, 10)); 14 | } 15 | 16 | static T GetValueOrDefault(IList list, int index) 17 | { 18 | return index >= 0 && index < list.Count ? list[index] : default(T); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Chapter14 6 | { 7 | [Description("Listing 14.1")] 8 | class LocalMethodIntro 9 | { 10 | static void Main() 11 | { 12 | int x = 10; 13 | PrintAndIncrementX(); 14 | PrintAndIncrementX(); 15 | Console.WriteLine($"After calls, x = {x}"); 16 | 17 | void PrintAndIncrementX() 18 | { 19 | Console.WriteLine($"x = {x}"); 20 | x++; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter04Com/SaveFileNew.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Word; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04Com 5 | { 6 | [Description("Listing 4.17")] 7 | class SaveFileNew 8 | { 9 | static void Main() 10 | { 11 | Application app = new Application { Visible = true }; 12 | Document doc = app.Documents.Add(); 13 | Paragraph para = doc.Paragraphs.Add(); 14 | para.Range.Text = "Simple new code"; 15 | 16 | doc.SaveAs2(FileName: "demo2.docx"); 17 | 18 | doc.Close(); 19 | app.Application.Quit(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter14 7 | { 8 | [Description("Listing 14.6")] 9 | class LocalMethodVariableCapture3 10 | { 11 | static void Main() 12 | { 13 | Action counter = CreateCounter(); 14 | counter(); 15 | counter(); 16 | } 17 | 18 | static Action CreateCounter() 19 | { 20 | int count = 0; 21 | return Count; 22 | void Count() => Console.WriteLine(count++); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter13/LargeStruct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter13 6 | { 7 | /// 8 | /// Meaningless, but pretty large as structs go... 9 | /// 10 | public readonly struct LargeStruct 11 | { 12 | public long X { get; } 13 | public long Y { get; } 14 | public long Z { get; } 15 | public double Weight { get; } 16 | public double Score { get; } 17 | 18 | public LargeStruct(long x, long y, long z, double weight, double score) => 19 | (X, Y, Z, Weight, Score) = (x, y, z, weight, score); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter04Com/ExcelDynamic.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Excel; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | 5 | namespace Chapter04Com 6 | { 7 | [Description("Listing 4.15")] 8 | class ExcelDynamic 9 | { 10 | static void Main() 11 | { 12 | var app = new Application { Visible = true }; 13 | app.Workbooks.Add(); 14 | Worksheet sheet = app.ActiveSheet; 15 | Range start = sheet.Cells[1, 1]; 16 | Range end = sheet.Cells[1, 20]; 17 | sheet.Range[start, end].Value = 18 | Enumerable.Range(1, 20).ToArray(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter09/QualifiedNameof.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter09 5 | { 6 | class OtherClass 7 | { 8 | public static int StaticMember => 3; 9 | public int InstanceMember => 3; 10 | } 11 | 12 | [Description("Listing 9.16")] 13 | class QualifiedNameof 14 | { 15 | static void Main() 16 | { 17 | OtherClass instance = null; 18 | Console.WriteLine(nameof(instance.InstanceMember)); 19 | Console.WriteLine(nameof(OtherClass.StaticMember)); 20 | Console.WriteLine(nameof(OtherClass.InstanceMember)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter10/CoordinatesUsingStatic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter10 6 | { 7 | [Description("Listing 10.2")] 8 | class CoordinatesUsingStatic 9 | { 10 | static void Main() 11 | { 12 | Console.WriteLine(PolarToCartesian(60, 20)); 13 | } 14 | 15 | static Point PolarToCartesian(double degrees, double magnitude) 16 | { 17 | double radians = degrees * PI / 180; 18 | return new Point( 19 | Cos(radians) * magnitude, 20 | Sin(radians) * magnitude); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | [Description("Listing 14.4")] 7 | class LocalMethodVariableCapture2 8 | { 9 | static void Main() 10 | { 11 | DateTime now = DateTime.UtcNow; 12 | int hour = now.Hour; 13 | if (hour > 5) 14 | { 15 | int minute = now.Minute; 16 | PrintHourAndMinute(); 17 | 18 | void PrintHourAndMinute() => 19 | Console.WriteLine($"hour = {hour}; minute = {minute}"); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter05/Chapter05.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net462 5 | Chapter05.Program 6 | 7.1 7 | True 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter10/UsingStaticExtensionMethods1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | using static System.Linq.Queryable; 5 | 6 | namespace Chapter10 7 | { 8 | [Description("Listing 10.3")] 9 | class UsingStaticExtensionMethods1 10 | { 11 | static void Main() 12 | { 13 | var query = new[] { "a", "bc", "d" }.AsQueryable(); 14 | 15 | Expression> expr = x => x.Length > 1; 16 | Func del = x => x.Length > 1; 17 | 18 | var valid = query.Where(expr); 19 | // var invalid = query.Where(del); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter12/DateTimeDeconstruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.8")] 7 | static class DateTimeDeconstruction 8 | { 9 | static void Deconstruct( 10 | this DateTime dateTime, 11 | out int year, out int month, out int day) => 12 | (year, month, day) = (dateTime.Year, dateTime.Month, dateTime.Day); 13 | 14 | static void Main() 15 | { 16 | DateTime now = DateTime.UtcNow; 17 | var (year, month, day) = now; 18 | Console.WriteLine($"{year:0000}-{month:00}-{day:00}"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter12/TupleDeconstructionOverview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.1")] 7 | class TupleDeconstructionOverview 8 | { 9 | static void Main() 10 | { 11 | var tuple = (10, "text"); 12 | 13 | var (a, b) = tuple; 14 | 15 | (int c, string d) = tuple; 16 | 17 | int e; 18 | string f; 19 | (e, f) = tuple; 20 | 21 | Console.WriteLine($"a: {a}; b: {b}"); 22 | Console.WriteLine($"c: {c}; d: {d}"); 23 | Console.WriteLine($"e: {e}; f: {f}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter13/RefReturnIndexer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.8")] 7 | class RefReturnIndexer 8 | { 9 | class ArrayHolder 10 | { 11 | private readonly int[] array = new int[10]; 12 | 13 | public ref int this[int index] => ref array[index]; 14 | } 15 | 16 | static void Main() 17 | { 18 | ArrayHolder holder = new ArrayHolder(); 19 | ref int x = ref holder[0]; 20 | ref int y = ref holder[0]; 21 | 22 | x = 20; 23 | Console.WriteLine(y); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter04/OptionalParameterIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04 5 | { 6 | [Description("Listing 4.14")] 7 | class OptionalParameterIntro 8 | { 9 | static void Method(int x, int y = 5, int z = 10) 10 | { 11 | Console.WriteLine("x={0}; y={1}; z={2}", x, y, z); 12 | } 13 | 14 | static void Main() 15 | { 16 | Method(1, 2, 3); 17 | Method(x: 1, y: 2, z: 3); 18 | Method(z: 3, y: 2, x: 1); 19 | Method(1, 2); 20 | Method(1, y: 2); 21 | Method(1, z: 3); 22 | Method(1); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter09/BirthdayInAllCultures.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | 5 | namespace Chapter09 6 | { 7 | [Description("Listing 9.2")] 8 | class BirthdayInAllCultures 9 | { 10 | static void Main() 11 | { 12 | var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); 13 | var birthDate = new DateTime(1976, 6, 19); 14 | foreach (var culture in cultures) 15 | { 16 | string text = string.Format(culture, "{0,-15} {1,12:d}", culture.Name, birthDate); 17 | Console.WriteLine(text); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter12/TupleDeconstructionAssignments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.3")] 7 | class TupleDeconstructionAssignments 8 | { 9 | static (int x, int y, string text) MethodReturningTuple() => (1, 2, "t"); 10 | 11 | static void Main() 12 | { 13 | int a = 20; 14 | int b = 30; 15 | string name = "before"; 16 | Console.WriteLine($"a: {a}; b: {b}; name: {name}"); 17 | 18 | (a, b, name) = MethodReturningTuple(); 19 | 20 | Console.WriteLine($"a: {a}; b: {b}; name: {name}"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter07/CallerInfoDemo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Chapter07 6 | { 7 | [Description("Listing 7.3")] 8 | class CallerInfoDemo 9 | { 10 | static void ShowInfo( 11 | [CallerFilePath] string file = null, 12 | [CallerLineNumber] int line = 0, 13 | [CallerMemberName] string member = null) 14 | { 15 | Console.WriteLine("{0}:{1} - {2}", file, line, member); 16 | } 17 | 18 | static void Main() 19 | { 20 | ShowInfo(); 21 | ShowInfo("LiesAndDamnedLies.java", -10); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter07/ForEachCapture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter07 6 | { 7 | [Description("Listing 7.1")] 8 | class ForEachCapture 9 | { 10 | static void Main() 11 | { 12 | List names = new List { "x", "y", "z" }; 13 | var actions = new List(); 14 | foreach (string name in names) 15 | { 16 | actions.Add(() => Console.WriteLine(name)); 17 | } 18 | foreach (Action action in actions) 19 | { 20 | action(); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter13/FixedSpan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class FixedSpan 6 | { 7 | unsafe static void Main() 8 | { 9 | string test = "Test"; 10 | ReadOnlySpan span = test; 11 | 12 | // Yes, this modifies a string... 13 | fixed (char* ptr = span) 14 | { 15 | *ptr = 'X'; 16 | } 17 | 18 | // But you could do that directly anyway 19 | fixed (char* ptr = test) 20 | { 21 | *(ptr + 1) = 'Y'; 22 | } 23 | // Prints XYst 24 | Console.WriteLine(test); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter02/NullableGetType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.10")] 7 | class NullableGetType 8 | { 9 | #pragma warning disable CS0219 // Variable is assigned but its value is never used 10 | static void Main() 11 | { 12 | Nullable noValue = new Nullable(); 13 | // Console.WriteLine(noValue.GetType()); 14 | 15 | Nullable someValue = new Nullable(5); 16 | Console.WriteLine(someValue.GetType()); 17 | } 18 | #pragma warning restore CS0219 // Variable is assigned but its value is never used 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter04/DynamicTypingAndExplicitInterfaceImplementation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | 6 | namespace Chapter04 7 | { 8 | [Description("Listing 4.13")] 9 | class DynamicTypingAndExplicitInterfaceImplementation 10 | { 11 | static void Main() 12 | { 13 | List list1 = new List(); 14 | //Console.WriteLine(list1.IsFixedSize); 15 | 16 | IList list2 = list1; 17 | Console.WriteLine(list2.IsFixedSize); 18 | 19 | dynamic list3 = list1; 20 | Console.WriteLine(list3.IsFixedSize); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter07/ForLoopCapture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter07 6 | { 7 | [Description("Listing 7.2")] 8 | class ForLoopCapture 9 | { 10 | static void Main() 11 | { 12 | List names = new List { "x", "y", "z" }; 13 | var actions = new List(); 14 | for (int i = 0; i < names.Count; i++) 15 | { 16 | actions.Add(() => Console.WriteLine(names[i])); 17 | } 18 | foreach (Action action in actions) 19 | { 20 | action(); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter04/InvalidLinqQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter04 7 | { 8 | [Description("Listing 4.10")] 9 | class InvalidLinqQuery 10 | { 11 | static void Main() 12 | { 13 | dynamic source = new List 14 | { 15 | 5, 16 | 2.75, 17 | TimeSpan.FromSeconds(45) 18 | }; 19 | // This fails at execution time: 20 | bool result = source.Any(); 21 | 22 | // This would work: 23 | // bool result = Enumerable.Any(source); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter06/SimpleAsyncMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter06 6 | { 7 | [Description("Listing 6.1")] 8 | class SimpleAsyncMethod 9 | { 10 | static async Task PrintAndWait(TimeSpan delay) 11 | { 12 | Console.WriteLine("Before first delay"); 13 | await Task.Delay(delay); 14 | Console.WriteLine("Between delays"); 15 | await Task.Delay(delay); 16 | Console.WriteLine("After second delay"); 17 | } 18 | 19 | static void Main() 20 | { 21 | PrintAndWait(TimeSpan.FromSeconds(1)).Wait(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter08/ReadOnlyListView.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter08 6 | { 7 | [Description("Listing 8.17")] 8 | public sealed class ReadOnlyListView : IReadOnlyList 9 | { 10 | private readonly IList list; 11 | 12 | public ReadOnlyListView(IList list) 13 | { 14 | this.list = list; 15 | } 16 | 17 | public T this[int index] => list[index]; 18 | public int Count => list.Count; 19 | public IEnumerator GetEnumerator() => list.GetEnumerator(); 20 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter05/ManuallyInducedCancellation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace Chapter05 5 | { 6 | class ManuallyInducedCancellation 7 | { 8 | static void Main() 9 | { 10 | Task task = ThrowCancellationException(); 11 | Console.WriteLine(task.Status); 12 | } 13 | 14 | #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously 15 | static async Task ThrowCancellationException() 16 | #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously 17 | { 18 | throw new OperationCanceledException(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter08/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter08 5 | { 6 | [Description("Listing 8.15, 6.16")] 7 | public sealed class Point 8 | { 9 | public double X { get; } 10 | public double Y { get; } 11 | 12 | public Point(double x, double y) 13 | { 14 | X = x; 15 | Y = y; 16 | } 17 | 18 | public double DistanceFromOrigin => Math.Sqrt(X * X + Y * Y); 19 | 20 | public static Point Add(Point left, Vector right) => left + right; 21 | 22 | public static Point operator +(Point left, Vector right) => 23 | new Point(left.X + right.X, left.Y + right.Y); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter04/DynamicLinqQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter04 7 | { 8 | [Description("Listing 4.9")] 9 | class DynamicLinqQuery 10 | { 11 | static void Main() 12 | { 13 | List source = new List 14 | { 15 | 5, 16 | 2.75, 17 | TimeSpan.FromSeconds(45) 18 | }; 19 | IEnumerable query = source.Select(x => x * 2); 20 | foreach (dynamic value in query) 21 | { 22 | Console.WriteLine(value); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter10/DictionaryInitialization.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter10 5 | { 6 | [Description("Listing 10.6")] 7 | class DictionaryInitialization 8 | { 9 | static void Main() 10 | { 11 | var objectInitializer = new Dictionary 12 | { 13 | ["A"] = 20, 14 | ["B"] = 30, 15 | ["B"] = 40 16 | }; 17 | 18 | var collectionInitializer = new Dictionary 19 | { 20 | { "A", 20 }, 21 | { "B", 30 }, 22 | { "B", 40 } 23 | }; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter02/PartialDemo1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.22")] 7 | class PartialDemo1 8 | { 9 | partial class PartialDemo 10 | { 11 | public static void MethodInPart1() 12 | { 13 | MethodInPart2(); 14 | } 15 | } 16 | 17 | partial class PartialDemo 18 | { 19 | private static void MethodInPart2() 20 | { 21 | Console.WriteLine("In MethodInPart2"); 22 | } 23 | } 24 | 25 | static void Main() 26 | { 27 | PartialDemo.MethodInPart1(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter04Com/NamedIndexers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Word; 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter04Com 6 | { 7 | [Description("Listing 4.18")] 8 | class NamedIndexers 9 | { 10 | static void Main() 11 | { 12 | Application app = new Application { Visible = false }; 13 | 14 | object missing = Type.Missing; 15 | SynonymInfo info = app.get_SynonymInfo("method", ref missing); 16 | Console.WriteLine("'method' has {0} meanings", info.MeaningCount); 17 | 18 | info = app.SynonymInfo["index"]; 19 | Console.WriteLine("'index' has {0} meanings", info.MeaningCount); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter10/ObjectInitializerIndexer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Chapter10 9 | { 10 | [Description("Listing 10.5")] 11 | class ObjectInitializerIndexer 12 | { 13 | static void Main() 14 | { 15 | string text = "This text needs truncating"; 16 | StringBuilder builder = new StringBuilder(text) 17 | { 18 | Length = 10, 19 | [9] = '\u2026' 20 | }; 21 | Console.OutputEncoding = Encoding.UTF8; 22 | Console.WriteLine(builder); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/DamnItOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.7")] 7 | class DamnItOperator 8 | { 9 | static void PrintLength(string? text) 10 | { 11 | if (!string.IsNullOrEmpty(text)) 12 | { 13 | Console.WriteLine($"{text}: {text!.Length}"); 14 | } 15 | else 16 | { 17 | Console.WriteLine("Empty or null"); 18 | } 19 | } 20 | 21 | static void Main() 22 | { 23 | PrintLength(null); 24 | PrintLength(""); 25 | PrintLength("foo"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter02/SimpleIterator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.11")] 9 | class SimpleIterator 10 | { 11 | static IEnumerable CreateSimpleIterator() 12 | { 13 | yield return 10; 14 | for (int i = 0; i < 3; i++) 15 | { 16 | yield return i; 17 | } 18 | yield return 20; 19 | } 20 | 21 | static void Main() 22 | { 23 | foreach (int value in CreateSimpleIterator()) 24 | { 25 | Console.WriteLine(value); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter03/ExtensionMethodChaining.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.17")] 9 | class ExtensionMethodChaining 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | IEnumerable query = words 15 | .Where(word => word.Length > 4) 16 | .OrderBy(word => word) 17 | .Select(word => word.ToUpper()); 18 | 19 | foreach (string word in query) 20 | { 21 | Console.WriteLine(word); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture1Equivalent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | [Description("Listing 14.3")] 7 | class LocalMethodVariableCapture1Equivalent 8 | { 9 | private struct MainLocals 10 | { 11 | public int i; 12 | } 13 | 14 | static void Main() 15 | { 16 | MainLocals locals = new MainLocals(); 17 | locals.i = 0; 18 | AddToI(5, ref locals); 19 | AddToI(10, ref locals); 20 | Console.WriteLine(locals.i); 21 | } 22 | 23 | static void AddToI(int amount, ref MainLocals locals) 24 | { 25 | locals.i += amount; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CSharp8/README.md: -------------------------------------------------------------------------------- 1 | The code in this solution has been updated to work with 2 | Visual Studio 2019 preview 2. Note that the members of 3 | `IAsyncEnumerator` have changed since chapter 15 was written; it 4 | now looks like this: 5 | 6 | ```csharp 7 | public interface IAsyncEnumerator : IAsyncDisposable 8 | { 9 | T Current { get; } 10 | ValueTask MoveNextAsync(); 11 | } 12 | ``` 13 | 14 | Likewise `IAsyncDisposable.DisposeAsync` now returns `ValueTask` 15 | rather than `Task`. 16 | 17 | I won't update this code with *all* C# 8 features - only those 18 | described in C# in Depth. For a more comprehensive set of demos - 19 | but ones which are geared towards live presentation as part of a 20 | conference talk - see https://github.com/jskeet/democode 21 | -------------------------------------------------------------------------------- /Chapter10/LoggingFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter10 5 | { 6 | [Description("Listing 10.16")] 7 | class LoggingFilter 8 | { 9 | static void Main() 10 | { 11 | try 12 | { 13 | UnreliableMethod(); 14 | } 15 | catch (Exception e) when (Log(e)) 16 | { 17 | } 18 | } 19 | 20 | static void UnreliableMethod() 21 | { 22 | throw new Exception("Bang!"); 23 | } 24 | 25 | static bool Log(Exception e) 26 | { 27 | Console.WriteLine($"{DateTime.UtcNow}: {e.GetType()} {e.Message}"); 28 | return false; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter02/TypeConstraints.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | public class TypeConstraints 9 | { 10 | static void PrintItems(List items) where T : IFormattable 11 | { 12 | CultureInfo culture = CultureInfo.InvariantCulture; 13 | foreach (T item in items) 14 | { 15 | Console.WriteLine(item.ToString(null, culture)); 16 | } 17 | } 18 | 19 | static void Main() 20 | { 21 | List items = new List(); 22 | items.Add(1.5m); 23 | items.Add(2.3m); 24 | PrintItems(items); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter12/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.4 and 10.7")] 7 | public sealed class Point 8 | { 9 | public double X { get; } 10 | public double Y { get; } 11 | 12 | public Point(double x, double y) => (X, Y) = (x, y); 13 | 14 | public void Deconstruct(out double x, out double y) => (x, y) = (X, Y); 15 | } 16 | 17 | [Description("Listing 12.7")] 18 | class PointDeconstruction 19 | { 20 | static void Main() 21 | { 22 | var point = new Point(1.5, 20); 23 | var (x, y) = point; 24 | Console.WriteLine($"x = {x}"); 25 | Console.WriteLine($"y = {y}"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter03/QueryWithLocalVariables.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.19")] 9 | class QueryWithLocalVariables 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | var tmp1 = Enumerable.Where(words, word => word.Length > 4); 15 | var tmp2 = Enumerable.OrderBy(tmp1, word => word); 16 | IEnumerable query = Enumerable.Select(tmp2, word => word.ToUpper()); 17 | 18 | foreach (string word in query) 19 | { 20 | Console.WriteLine(word); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter13/ImplicitParameterCopy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | class ImplicitParameterCopy 6 | { 7 | // No copying for each property; the parameter is already a copy of the caller's value. 8 | public void PrintYearMonthDay(YearMonthDay input) => 9 | Console.WriteLine($"{input.Year} {input.Month} {input.Day}"); 10 | 11 | // Implicit copy for each property. 12 | public void PrintYearMonthDay(in YearMonthDay input) => 13 | Console.WriteLine($"{input.Year} {input.Month} {input.Day}"); 14 | 15 | // No value copying at all! 16 | public void PrintYearMonthDay(in ReadOnlyYearMonthDay input) => 17 | Console.WriteLine($"{input.Year} {input.Month} {input.Day}"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter03/QueryExpression1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.20")] 9 | class QueryExpression1 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | IEnumerable query = from word in words 15 | where word.Length > 4 16 | orderby word 17 | select word.ToUpper(); 18 | 19 | foreach (string word in query) 20 | { 21 | Console.WriteLine(word); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/FibonacciWithTuples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.6")] 9 | class FibonacciWithTuples 10 | { 11 | static void Main() 12 | { 13 | foreach (var value in Fibonacci().Take(10)) 14 | { 15 | Console.WriteLine(value); 16 | } 17 | } 18 | 19 | static IEnumerable Fibonacci() 20 | { 21 | var pair = (current: 0, next: 1); 22 | while (true) 23 | { 24 | yield return pair.current; 25 | pair = (pair.next, pair.current + pair.next); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter13/RefLocalArrays.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Chapter13 4 | { 5 | [Description("Listing 13.3")] 6 | class RefLocalArrays 7 | { 8 | static void Main() 9 | { 10 | var array = new (int x, int y)[10]; 11 | // First initialize the array 12 | for (int i = 0; i < array.Length; i++) 13 | { 14 | array[i] = (i, i); 15 | } 16 | 17 | // Then increment x and double y for each 18 | // element in the array 19 | for (int i = 0; i < array.Length; i++) 20 | { 21 | ref var element = ref array[i]; 22 | element.x++; 23 | element.y *= 2; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter04/DynamicJsonParsing.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter04 6 | { 7 | [Description("Listing 4.6")] 8 | class DynamicJsonParsing 9 | { 10 | static void Main() 11 | { 12 | string json = @" 13 | { 14 | 'name': 'Jon Skeet', 15 | 'address': { 16 | 'town': 'Reading', 17 | 'country': 'UK' 18 | } 19 | }".Replace('\'', '"'); 20 | 21 | JObject obj1 = JObject.Parse(json); 22 | Console.WriteLine(obj1["address"]["town"]); 23 | 24 | dynamic obj2 = obj1; 25 | Console.WriteLine(obj2.address.town); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter06/AwaitInsideLoop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter06 6 | { 7 | [Description("Listing 6.7")] 8 | class AwaitInsideLoop 9 | { 10 | static async Task AwaitInLoop(TimeSpan delay) 11 | { 12 | Console.WriteLine("Before loop"); 13 | for (int i = 0; i < 3; i++) 14 | { 15 | Console.WriteLine("Before await in loop"); 16 | await Task.Delay(delay); 17 | Console.WriteLine("After await in loop"); 18 | } 19 | Console.WriteLine("After loop delay"); 20 | } 21 | 22 | static void Main() 23 | { 24 | AwaitInLoop(TimeSpan.FromSeconds(1)).Wait(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter07/DynamicAndCallerInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Chapter07 6 | { 7 | [Description("Listing 7.6")] 8 | class DynamicAndCallerInfo 9 | { 10 | static void ShowLine(string message, [CallerLineNumber] int line = 0) 11 | { 12 | Console.WriteLine("{0}: {1}", line, message); 13 | } 14 | 15 | static int GetLineNumber([CallerLineNumber] int line = 0) 16 | { 17 | return line; 18 | } 19 | 20 | static void Main() 21 | { 22 | dynamic message = "Some message"; 23 | ShowLine(message); 24 | ShowLine((string) message); 25 | ShowLine(message, GetLineNumber()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter12/TupleDeconstructionEvaluationOrderingExplained.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Text; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.6")] 8 | class TupleDeconstructionEvaluationOrderingExplained 9 | { 10 | static void Main() 11 | { 12 | StringBuilder builder = new StringBuilder("12345"); 13 | StringBuilder original = builder; 14 | 15 | StringBuilder targetForLength = builder; 16 | 17 | (StringBuilder, int) tuple = (new StringBuilder("67890"), 3); 18 | 19 | builder = tuple.Item1; 20 | targetForLength.Length = tuple.Item2; 21 | 22 | Console.WriteLine(original); 23 | Console.WriteLine(builder); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/BrokenInitialExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | // This example is meant to be in C# 7, so disable the C# 8 features. 5 | #nullable disable 6 | 7 | namespace NullableReferences 8 | { 9 | [Description("Listing 15.1")] 10 | class BrokenInitialExample 11 | { 12 | public class Customer 13 | { 14 | public string Name { get; set; } 15 | public Address Address { get; set; } 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | } 22 | 23 | static void Main() 24 | { 25 | Customer customer = new Customer { Name = "Jon" }; 26 | Console.WriteLine(customer.Address.Country); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter10/SpecializedAddExtensionMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter10 5 | { 6 | static class PersonDictionaryExtensions 7 | { 8 | public static void Add( 9 | this Dictionary dictionary, Person person) 10 | { 11 | dictionary.Add(person.Name, person); 12 | } 13 | } 14 | 15 | [Description("Listing 10.10")] 16 | class SpecializedAddExtensionMethod 17 | { 18 | static void Main() 19 | { 20 | Dictionary dictionary = new Dictionary 21 | { 22 | { new Person { Name = "Jon" } }, 23 | { new Person { Name = "Holly" } } 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/EqualityOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter11 5 | { 6 | [Description("Listing 11.X")] 7 | class EqualityOperators 8 | { 9 | static void Main() 10 | { 11 | var t1 = (x: "x", y: "y", z: 1); 12 | var t2 = ("x", "y", 1); 13 | Console.WriteLine(t1 == t2); 14 | 15 | Console.WriteLine(t1.Item1 == t2.Item1 && 16 | t1.Item2 == t2.Item2 && 17 | t1.Item3 == t2.Item3); 18 | 19 | Console.WriteLine(t1 != t2); 20 | Console.WriteLine(t1.Item1 != t2.Item1 && 21 | t1.Item2 != t2.Item2 && 22 | t1.Item3 != t2.Item3); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/RegularComparisons.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | 5 | namespace Chapter11 6 | { 7 | [Description("Listing 11.9")] 8 | class RegularComparisons 9 | { 10 | static void Main() 11 | { 12 | var points = new[] 13 | { 14 | (1, 2), (10, 3), (-1, 5), (2, 1), 15 | (10, 3), (2, 1), (1, 1) 16 | }; 17 | 18 | var distinctPoints = points.Distinct(); 19 | Console.WriteLine($"{distinctPoints.Count()} distinct points"); 20 | Console.WriteLine("Points in order:"); 21 | foreach (var point in distinctPoints.OrderBy(p => p)) 22 | { 23 | Console.WriteLine(point); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter13/InParameterOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | 5 | namespace Chapter13 6 | { 7 | [Description("Listing 13.12")] 8 | class InParameterOptions 9 | { 10 | static void PrintDateTime(in DateTime value) 11 | { 12 | string text = value.ToString( 13 | "yyyy-MM-dd'T'HH:mm:ss", 14 | CultureInfo.InvariantCulture); 15 | Console.WriteLine(text); 16 | } 17 | 18 | static void Main() 19 | { 20 | DateTime start = DateTime.UtcNow; 21 | PrintDateTime(start); 22 | PrintDateTime(in start); 23 | PrintDateTime(start.AddMinutes(1)); 24 | //PrintDateTime(in start.AddMinutes(1)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter02/IteratorBlockWithFinally.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.14")] 9 | internal static class IteratorBlockWithFinally 10 | { 11 | internal static IEnumerable Iterator() 12 | { 13 | try 14 | { 15 | Console.WriteLine("Before first yield"); 16 | yield return "first"; 17 | Console.WriteLine("Between yields"); 18 | yield return "second"; 19 | Console.WriteLine("After second yield"); 20 | } 21 | finally 22 | { 23 | Console.WriteLine("In finally block"); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter03/NestedMethodCalls.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.18")] 9 | class NestedMethodCalls 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | IEnumerable query = 15 | Enumerable.Select( 16 | Enumerable.OrderBy( 17 | Enumerable.Where(words, word => word.Length > 4), 18 | word => word), 19 | word => word.ToUpper()); 20 | 21 | foreach (string word in query) 22 | { 23 | Console.WriteLine(word); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter05/AsyncLambda.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.8")] 8 | class AsyncLambda 9 | { 10 | static void Main() 11 | { 12 | Func> function = async x => 13 | { 14 | Console.WriteLine("Starting... x={0}", x); 15 | await Task.Delay(x * 1000); 16 | Console.WriteLine("Finished... x={0}", x); 17 | return x * 2; 18 | }; 19 | Task first = function(5); 20 | Task second = function(3); 21 | Console.WriteLine("First result: {0}", first.Result); 22 | Console.WriteLine("Second result: {0}", second.Result); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter06/AsyncMethodWithSimpleLoop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter06 6 | { 7 | [Description("Listing 6.6")] 8 | class AsyncMethodWithSimpleLoop 9 | { 10 | static async Task PrintAndWaitWithSimpleLoop(TimeSpan delay) 11 | { 12 | Console.WriteLine("Before first delay"); 13 | await Task.Delay(delay); 14 | for (int i = 0; i < 3; i++) 15 | { 16 | Console.WriteLine("Between delays"); 17 | } 18 | await Task.Delay(delay); 19 | Console.WriteLine("After second delay"); 20 | } 21 | 22 | static void Main() 23 | { 24 | PrintAndWaitWithSimpleLoop(TimeSpan.FromSeconds(1)).Wait(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter13/ReadOnlyArrayView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | class ReadOnlyArrayView 7 | { 8 | private readonly T[] values; 9 | 10 | public ReadOnlyArrayView(T[] values) => this.values = values; 11 | 12 | public ref readonly T this[int index] => ref values[index]; 13 | } 14 | 15 | [Description("Listing 13.11")] 16 | class ReadOnlyArrayViewDemo 17 | { 18 | static void Main() 19 | { 20 | var array = new int[] { 10, 20, 30 }; 21 | var view = new ReadOnlyArrayView(array); 22 | 23 | ref readonly int element = ref view[0]; 24 | Console.WriteLine(element); 25 | array[0] = 100; 26 | Console.WriteLine(element); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter02/StaticClasses.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.24")] 9 | class StaticClasses 10 | { 11 | static class StaticClassDemo 12 | { 13 | public static void StaticMethod() { } 14 | 15 | //public void InstanceMethod() { } 16 | 17 | public class RegularNestedClass 18 | { 19 | public void InstanceMethod() { } 20 | } 21 | } 22 | 23 | static void Main() 24 | { 25 | StaticClassDemo.StaticMethod(); 26 | 27 | //StaticClassDemo localVariable = null; 28 | //List list = new List(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter03/ExpressionTreeIntroImpl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | 5 | namespace Chapter03 6 | { 7 | [Description("Listing 3.13")] 8 | class ExpressionTreeIntroImpl 9 | { 10 | static void Main() 11 | { 12 | ParameterExpression xParameter = Expression.Parameter(typeof(int), "x"); 13 | ParameterExpression yParameter = Expression.Parameter(typeof(int), "y"); 14 | Expression body = Expression.Add(xParameter, yParameter); 15 | ParameterExpression[] parameters = new[] { xParameter, yParameter }; 16 | 17 | Expression> adder = 18 | Expression.Lambda>(body, parameters); 19 | Console.WriteLine(adder); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter13/YearMonthDay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | public struct YearMonthDay 6 | { 7 | public int Year { get; } 8 | public int Month { get; } 9 | public int Day { get; } 10 | 11 | public YearMonthDay(int year, int month, int day) => 12 | (Year, Month, Day) = (year, month, day); 13 | } 14 | 15 | public readonly struct ReadOnlyYearMonthDay 16 | { 17 | public int X 18 | { 19 | get => 0; 20 | set => Console.WriteLine(value); 21 | } 22 | 23 | public int Year { get; } 24 | public int Month { get; } 25 | public int Day { get; } 26 | 27 | public ReadOnlyYearMonthDay(int year, int month, int day) => 28 | (Year, Month, Day) = (year, month, day); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/GeoServiceDemo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.19")] 8 | public class GeoServiceDemo 9 | { 10 | async static Task Main() 11 | { 12 | var fakeService = new FakeGeoService(); 13 | fakeService.AddPage("London", "Paris", "Washington"); 14 | fakeService.AddPage(); // Empty pages are valid 15 | fakeService.AddPage("Nairobi", "Sydney", "New Delhi"); 16 | fakeService.AddPage("Moscow"); 17 | 18 | var client = new GeoClient(fakeService); 19 | 20 | await foreach (var city in client.ListCitiesAsync()) 21 | { 22 | Console.WriteLine(city); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter03/QueryExpression2Impl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.22")] 9 | class QueryExpression2Impl 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | IEnumerable query = words 15 | .Select(word => new { word, length = word.Length }) 16 | .Where(tmp => tmp.length > 4) 17 | .OrderBy(tmp => tmp.length) 18 | .Select(tmp => string.Format("{0}: {1}", tmp.length, tmp.word.ToUpper())); 19 | 20 | foreach (string item in query) 21 | { 22 | Console.WriteLine(item); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter10/CollectionInitializerExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter10 7 | { 8 | public static class StringListExtensions 9 | { 10 | public static void Add(this List list, int value, int count = 1) 11 | { 12 | list.AddRange(Enumerable.Repeat(value.ToString(), count)); 13 | } 14 | } 15 | 16 | [Description("Listing 10.9")] 17 | class CollectionInitializerExtensionMethods 18 | { 19 | static void Main() 20 | { 21 | List strings = new List 22 | { 23 | 10, 24 | "hello", 25 | { 20, 3 } 26 | }; 27 | Console.WriteLine(strings.Count); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture3Equivalent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter14 7 | { 8 | [Description("Listing 14.7")] 9 | class LocalMethodVariableCapture3Equivalent 10 | { 11 | static void Main() 12 | { 13 | Action counter = CreateCounter(); 14 | counter(); 15 | counter(); 16 | } 17 | 18 | static Action CreateCounter() 19 | { 20 | CountHolder holder = new CountHolder(); 21 | holder.count = 0; 22 | return holder.Count; 23 | } 24 | 25 | private class CountHolder 26 | { 27 | public int count; 28 | 29 | public void Count() => Console.WriteLine(count++); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter11/FibonacciWithoutTuples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.5")] 9 | class FibonacciWithoutTuples 10 | { 11 | static void Main() 12 | { 13 | foreach (var value in Fibonacci().Take(10)) 14 | { 15 | Console.WriteLine(value); 16 | } 17 | } 18 | 19 | static IEnumerable Fibonacci() 20 | { 21 | int current = 0; 22 | int next = 1; 23 | while (true) 24 | { 25 | yield return current; 26 | int nextNext = current + next; 27 | current = next; 28 | next = nextNext; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter04/DynamicLinqQueryWithQueryable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter04 7 | { 8 | [Description("Listing 4.11")] 9 | class DynamicLinqQueryWithQueryable 10 | { 11 | static void Main() 12 | { 13 | List source = new List 14 | { 15 | 5, 16 | 2.75, 17 | TimeSpan.FromSeconds(45) 18 | }; 19 | 20 | /* Uncomment to see the compilation failure 21 | IEnumerable query = source 22 | .AsQueryable() 23 | .Select(x => x * 2); 24 | foreach (dynamic value in query) 25 | { 26 | Console.WriteLine(value); 27 | }*/ 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter02/NamesWithArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.1")] 7 | public class NamesWithArray 8 | { 9 | static string[] GenerateNames() 10 | { 11 | string[] names = new string[4]; 12 | names[0] = "Gamma"; 13 | names[1] = "Vlissides"; 14 | names[2] = "Johnson"; 15 | names[3] = "Helm"; 16 | return names; 17 | } 18 | 19 | static void PrintNames(string[] names) 20 | { 21 | foreach (string name in names) 22 | { 23 | Console.WriteLine(name); 24 | } 25 | } 26 | 27 | static void Main() 28 | { 29 | string[] names = GenerateNames(); 30 | PrintNames(names); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter13/GenerateRandomString1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.20")] 7 | class GenerateRandomString1 8 | { 9 | static string Generate(string alphabet, Random random, int length) 10 | { 11 | char[] chars = new char[length]; 12 | for (int i = 0; i < length; i++) 13 | { 14 | chars[i] = alphabet[random.Next(alphabet.Length)]; 15 | } 16 | return new string(chars); 17 | } 18 | 19 | static void Main() 20 | { 21 | string alphabet = "abcdefghijklmnopqrstuvwxyz"; 22 | Random random = new Random(); 23 | Console.WriteLine(Generate(alphabet, random, 10)); 24 | Console.WriteLine(Generate(alphabet, random, 20)); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /CSharp8/Chapter15/IGeoService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.17")] 8 | public interface IGeoService 9 | { 10 | Task ListCitiesAsync(ListCitiesRequest request); 11 | } 12 | 13 | public class ListCitiesRequest 14 | { 15 | public string? PageToken { get; } 16 | public ListCitiesRequest(string? pageToken) => 17 | PageToken = pageToken; 18 | } 19 | 20 | public class ListCitiesResponse 21 | { 22 | public string? NextPageToken { get; } 23 | public List Cities { get; } 24 | 25 | public ListCitiesResponse(string? nextPageToken, List cities) => 26 | (NextPageToken, Cities) = (nextPageToken, cities); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter10/FirstExceptionFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter10 5 | { 6 | [Description("Listing 10.13")] 7 | class FirstExceptionFilter 8 | { 9 | static void Main() 10 | { 11 | string[] messages = 12 | { 13 | "You can catch this", 14 | "You can catch this too", 15 | "This won't be caught" 16 | }; 17 | foreach (string message in messages) 18 | { 19 | try 20 | { 21 | throw new Exception(message); 22 | } 23 | catch (Exception e) when (e.Message.Contains("catch")) 24 | { 25 | Console.WriteLine($"Caught '{e.Message}'"); 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter03/QueryExpression2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter03 7 | { 8 | [Description("Listing 3.21")] 9 | class QueryExpression2 10 | { 11 | static void Main() 12 | { 13 | string[] words = { "keys", "coat", "laptop", "bottle" }; 14 | IEnumerable query = from word in words 15 | let length = word.Length 16 | where length > 4 17 | orderby length 18 | select string.Format("{0}: {1}", length, word.ToUpper()); 19 | 20 | foreach (string item in query) 21 | { 22 | Console.WriteLine(item); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter12/ConstantPatterns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.12")] 7 | class ConstantPatterns 8 | { 9 | static void Match(object input) 10 | { 11 | if (input is "hello") 12 | Console.WriteLine("Input is string hello"); 13 | else if (input is 5L) 14 | Console.WriteLine("Input is long 5"); 15 | else if (input is 10) 16 | Console.WriteLine("Input is int 10"); 17 | else 18 | Console.WriteLine("Input didn't match hello, long 5 or int 10"); 19 | } 20 | 21 | static void Main() 22 | { 23 | Match("hello"); 24 | Match(5L); 25 | Match(7); 26 | Match(10); 27 | Match(10L); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter02/IteratorBlockWithFinallyDemo2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 2.17")] 8 | class IteratorBlockWithFinallyDemo3 9 | { 10 | static void Main() 11 | { 12 | IEnumerable enumerable = IteratorBlockWithFinally.Iterator(); 13 | using (IEnumerator enumerator = enumerable.GetEnumerator()) 14 | { 15 | while (enumerator.MoveNext()) 16 | { 17 | string value = enumerator.Current; 18 | Console.WriteLine("Received value: {0}", value); 19 | if (value != null) 20 | { 21 | break; 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter03/CapturingMultipleInstantiations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 3.8")] 8 | class CapturingMultipleInstantiations 9 | { 10 | static List CreateActions() 11 | { 12 | List actions = new List(); 13 | for (int i = 0; i < 5; i++) 14 | { 15 | string text = string.Format("message {0}", i); 16 | actions.Add(() => Console.WriteLine(text)); 17 | } 18 | return actions; 19 | } 20 | 21 | static void Main() 22 | { 23 | List actions = CreateActions(); 24 | foreach (Action action in actions) 25 | { 26 | action(); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter13/GenerateRandomString3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.22")] 7 | class GenerateRandomString3 8 | { 9 | static string Generate(string alphabet, Random random, int length) 10 | { 11 | Span chars = stackalloc char[length]; 12 | for (int i = 0; i < length; i++) 13 | { 14 | chars[i] = alphabet[random.Next(alphabet.Length)]; 15 | } 16 | return new string(chars); 17 | } 18 | 19 | static void Main() 20 | { 21 | string alphabet = "abcdefghijklmnopqrstuvwxyz"; 22 | Random random = new Random(); 23 | Console.WriteLine(Generate(alphabet, random, 10)); 24 | Console.WriteLine(Generate(alphabet, random, 20)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter13/RefConditional.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter13 6 | { 7 | [Description("Listing 13.9")] 8 | class RefConditional 9 | { 10 | static void Main() 11 | { 12 | var counts = CountEvenAndOdd(new[] { 1, 5, 2, 3, 4 }); 13 | Console.WriteLine($"Even: {counts.even}"); 14 | Console.WriteLine($"Odd: {counts.odd}"); 15 | } 16 | 17 | static (int even, int odd) CountEvenAndOdd(IEnumerable values) 18 | { 19 | var result = (even: 0, odd: 0); 20 | foreach (var value in values) 21 | { 22 | ref int counter = ref (value & 1) == 0 ? ref result.even : ref result.odd; 23 | counter++; 24 | } 25 | return result; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter05/AwaitCompletedTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.3")] 8 | class AwaitCompletedTask 9 | { 10 | static void Main() 11 | { 12 | Task task = DemoCompletedAsync(); 13 | Console.WriteLine("Method returned"); 14 | // Safe in a console app - no synchronization context 15 | task.Wait(); 16 | Console.WriteLine("Task completed"); 17 | } 18 | 19 | static async Task DemoCompletedAsync() 20 | { 21 | Console.WriteLine("Before first await"); 22 | await Task.FromResult(10); 23 | Console.WriteLine("Between awaits"); 24 | await Task.Delay(1000); 25 | Console.WriteLine("After second await"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter12/TypePatternWithNullableType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.14")] 7 | class TypePatternWithNullableType 8 | { 9 | static void Main() 10 | { 11 | CheckType(null); 12 | CheckType(5); 13 | CheckType("text"); 14 | CheckType(null); 15 | CheckType(5); 16 | CheckType("text"); 17 | } 18 | 19 | static void CheckType(object value) 20 | { 21 | if (value is T t) 22 | { 23 | Console.WriteLine($"Yes! {t} is a {typeof(T)}"); 24 | } 25 | else 26 | { 27 | Console.WriteLine($"No! {value ?? "null"} is not a {typeof(T)}"); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter13/GenerateRandomString2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.21")] 7 | class GenerateRandomString2 8 | { 9 | unsafe static string Generate(string alphabet, Random random, int length) 10 | { 11 | char* chars = stackalloc char[length]; 12 | for (int i = 0; i < length; i++) 13 | { 14 | chars[i] = alphabet[random.Next(alphabet.Length)]; 15 | } 16 | return new string(chars); 17 | } 18 | 19 | static void Main() 20 | { 21 | string alphabet = "abcdefghijklmnopqrstuvwxyz"; 22 | Random random = new Random(); 23 | Console.WriteLine(Generate(alphabet, random, 10)); 24 | Console.WriteLine(Generate(alphabet, random, 20)); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter13/ReadonlyStructUnsafeViolation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter13 4 | { 5 | // Sample just to show how unsafe code can violate the readonly modifier. 6 | 7 | readonly struct EvilStruct 8 | { 9 | public int Value { get; } 10 | 11 | public EvilStruct(int value) => Value = value; 12 | 13 | public unsafe void Mutate(int newValue) 14 | { 15 | fixed (EvilStruct* me = &this) 16 | { 17 | *me = new EvilStruct(newValue); 18 | } 19 | } 20 | } 21 | 22 | class ReadonlyStructUnsafeViolation 23 | { 24 | private static readonly EvilStruct evil = new EvilStruct(10); 25 | 26 | static void Main() 27 | { 28 | Console.WriteLine(evil.Value); 29 | evil.Mutate(20); 30 | Console.WriteLine(evil.Value); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/NullableAddressFix1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.4")] 7 | class NullableAddressFix1 8 | { 9 | public class Customer 10 | { 11 | public string Name { get; set; } 12 | public Address? Address { get; set; } 13 | 14 | public Customer(string name) => 15 | Name = name; 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | 22 | public Address(string country) => 23 | Country = country; 24 | } 25 | 26 | static void Main() 27 | { 28 | Customer customer = new Customer("Jon"); 29 | Console.WriteLine(customer.Address?.Country ?? "(Address unknown)"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter14/GenericConstraints.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | enum SampleEnum { } 7 | 8 | [Description("Listing 14.12")] 9 | class GenericConstraints 10 | { 11 | static void EnumMethod() where T : struct, Enum 12 | { 13 | } 14 | 15 | static void DelegateMethod() where T : Delegate 16 | { 17 | } 18 | 19 | static void UnmanagedMethod() where T : unmanaged 20 | { 21 | } 22 | 23 | static void Main() 24 | { 25 | EnumMethod(); 26 | // EnumMethod(); 27 | DelegateMethod(); 28 | DelegateMethod(); 29 | DelegateMethod(); 30 | 31 | UnmanagedMethod(); 32 | //UnmanagedMethod(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter02/NamesWithArrayList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 2.2")] 8 | public class NamesWithArrayList 9 | { 10 | static ArrayList GenerateNames() 11 | { 12 | ArrayList names = new ArrayList(); 13 | names.Add("Gamma"); 14 | names.Add("Vlissides"); 15 | names.Add("Johnson"); 16 | names.Add("Helm"); 17 | return names; 18 | } 19 | 20 | static void PrintNames(ArrayList names) 21 | { 22 | foreach (string name in names) 23 | { 24 | Console.WriteLine(name); 25 | } 26 | } 27 | 28 | static void Main() 29 | { 30 | ArrayList names = GenerateNames(); 31 | PrintNames(names); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter06/AwaitInsideTryFinally.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter06 6 | { 7 | [Description("Listing 6.9")] 8 | class AwaitInsideTryFinally 9 | { 10 | static async Task AwaitInTryFinally(TimeSpan delay) 11 | { 12 | Console.WriteLine("Before try block"); 13 | try 14 | { 15 | Console.WriteLine("Before await"); 16 | await Task.Delay(delay); 17 | Console.WriteLine("After await"); 18 | } 19 | finally 20 | { 21 | Console.WriteLine("In finally block"); 22 | } 23 | Console.WriteLine("After finally block"); 24 | } 25 | 26 | static void Main() 27 | { 28 | AwaitInTryFinally(TimeSpan.FromSeconds(1)).Wait(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter05/PrintPageLength.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | 6 | namespace Chapter05 7 | { 8 | [Description("Listing 5.2")] 9 | class ReturnFromAsync 10 | { 11 | static readonly HttpClient client = new HttpClient(); 12 | 13 | static async Task GetPageLengthAsync(string url) 14 | { 15 | Task fetchTextTask = client.GetStringAsync(url); 16 | int length = (await fetchTextTask).Length; 17 | return length; 18 | } 19 | 20 | static void PrintPageLength() 21 | { 22 | Task lengthTask = 23 | GetPageLengthAsync("http://csharpindepth.com"); 24 | Console.WriteLine(lengthTask.Result); 25 | } 26 | 27 | static void Main() 28 | { 29 | PrintPageLength(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter09/FormatDateInvariant.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using static System.FormattableString; 5 | 6 | namespace Chapter09 7 | { 8 | [Description("Listing 9.6")] 9 | class FormatDateInvariant 10 | { 11 | static void Main() 12 | { 13 | DateTime date = DateTime.UtcNow; 14 | 15 | string parameter1 = string.Format( 16 | CultureInfo.InvariantCulture, 17 | "x={0:yyyy-MM-dd}", 18 | date); 19 | 20 | string parameter2 = 21 | ((FormattableString)$"x={date:yyyy-MM-dd}") 22 | .ToString(CultureInfo.InvariantCulture); 23 | 24 | string parameter3 = 25 | FormattableString.Invariant($"x={date:yyyy-MM-dd}"); 26 | 27 | string parameter4 = Invariant($"x={date:yyyy-MM-dd}"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter12/FizzBuzz.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter12 6 | { 7 | class FizzBuzz 8 | { 9 | static void Main() 10 | { 11 | for (int i = 1; i < 50; i++) 12 | { 13 | PrintFizzBuzz(i); 14 | } 15 | } 16 | 17 | static void PrintFizzBuzz(int n) 18 | { 19 | switch (n) 20 | { 21 | case var _ when n % 3 == 0: 22 | Console.Write("Fizz"); 23 | goto case 0; 24 | case 0: 25 | break; 26 | case var _ when n % 5 == 0: 27 | Console.Write("Buzz"); 28 | break; 29 | default: 30 | Console.WriteLine(n); 31 | break; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/EverythingNonNullable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.2")] 7 | class EverythingNonNullable 8 | { 9 | public class Customer 10 | { 11 | public string Name { get; set; } 12 | public Address Address { get; set; } 13 | 14 | public Customer(string name, Address address) => 15 | (Name, Address) = (name, address); 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | 22 | public Address(string country) => 23 | Country = country; 24 | } 25 | 26 | static void Main() 27 | { 28 | Customer customer = new Customer("Jon", new Address("UK")); 29 | Console.WriteLine(customer.Address.Country); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter10/AddRangeAsAdd.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chapter10 8 | { 9 | static class ListExtensions 10 | { 11 | public static void Add(this List list, IEnumerable collection) 12 | { 13 | list.AddRange(collection); 14 | } 15 | } 16 | class AddRangeAsAdd 17 | { 18 | static void Main() 19 | { 20 | List allContacts = new List 21 | { 22 | new Person { Name = "Holly", Town = "Reading" }, 23 | new Person { Name = "Gareth", Town = "Cambridge" } 24 | }; 25 | 26 | var jon = new Person 27 | { 28 | Name = "Jon", 29 | Contacts = { allContacts.Where(c => c.Town == "Reading") } 30 | }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/GeoClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter15 5 | { 6 | [Description("Listing 15.18 and 15.20")] 7 | public class GeoClient 8 | { 9 | private readonly IGeoService service; 10 | 11 | public GeoClient(IGeoService service) => 12 | this.service = service; 13 | 14 | public async IAsyncEnumerable ListCitiesAsync() 15 | { 16 | string? pageToken = null; 17 | do 18 | { 19 | var request = new ListCitiesRequest(pageToken); 20 | var response = await service.ListCitiesAsync(request); 21 | foreach (var city in response.Cities) 22 | { 23 | yield return city; 24 | } 25 | pageToken = response.NextPageToken; 26 | } while (pageToken != null); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter04/ExpandoObjectIntroduction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Dynamic; 5 | 6 | namespace Chapter04 7 | { 8 | [Description("Listing 4.5")] 9 | class ExpandoObjectIntroduction 10 | { 11 | static void Main() 12 | { 13 | dynamic expando = new ExpandoObject(); 14 | expando.SomeData = "Some data"; 15 | Action action = input => Console.WriteLine("The input was '{0}'", input); 16 | expando.FakeMethod = action; 17 | 18 | Console.WriteLine(expando.SomeData); 19 | expando.FakeMethod("hello"); 20 | 21 | IDictionary dictionary = expando; 22 | Console.WriteLine("Keys: {0}", string.Join(", ", dictionary.Keys)); 23 | 24 | dictionary["OtherData"] = "other"; 25 | Console.WriteLine(expando.OtherData); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter02/FibonacciSequence.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.13")] 9 | class FibonacciSequence 10 | { 11 | static IEnumerable Fibonacci() 12 | { 13 | int current = 0; 14 | int next = 1; 15 | while (true) 16 | { 17 | yield return current; 18 | int oldCurrent = current; 19 | current = next; 20 | next = next + oldCurrent; 21 | } 22 | } 23 | 24 | static void Main() 25 | { 26 | foreach (var value in Fibonacci()) 27 | { 28 | Console.WriteLine(value); 29 | if (value > 1000) 30 | { 31 | break; 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter05/LazyArgumentValidation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.5")] 8 | class LazyArgumentValidation 9 | { 10 | static void Main() 11 | { 12 | MainAsync().GetAwaiter().GetResult(); 13 | } 14 | 15 | static async Task MainAsync() 16 | { 17 | Task task = ComputeLengthAsync(null); 18 | Console.WriteLine("Fetched the task"); 19 | int length = await task; 20 | Console.WriteLine("Length: {0}", length); 21 | } 22 | 23 | static async Task ComputeLengthAsync(string text) 24 | { 25 | if (text == null) 26 | { 27 | throw new ArgumentNullException("text"); 28 | } 29 | await Task.Delay(500); 30 | return text.Length; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter11/Game.cs: -------------------------------------------------------------------------------- 1 | using NodaTime; 2 | using System.Collections.Generic; 3 | 4 | namespace Chapter11 5 | { 6 | // Used by listings 11.11 and 11.12 7 | class Game 8 | { 9 | public string PlayerName { get; } 10 | public int Score { get; } 11 | public LocalDate Date { get; } 12 | 13 | private Game(string playerName, int score, LocalDate date) 14 | { 15 | PlayerName = playerName; 16 | Score = score; 17 | Date = date; 18 | } 19 | 20 | public static IEnumerable AllGames { get; } = new[] 21 | { 22 | new Game("Fiona", 10, new LocalDate(2018, 5, 31)), 23 | new Game("Jorge", 30, new LocalDate(2018, 5, 31)), 24 | new Game("Don", 20, new LocalDate(2018, 5, 31)), 25 | new Game("Jemima", 45, new LocalDate(2018, 6, 1)), 26 | new Game("Rosie", 35, new LocalDate(2018, 6, 1)), 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter14/SelectBeforeLocalMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter14 6 | { 7 | internal static class SelectBeforeLocalMethods 8 | { 9 | public static IEnumerable Select( 10 | this IEnumerable source, 11 | Func selector) 12 | { 13 | Preconditions.CheckNotNull(source, nameof(source)); 14 | Preconditions.CheckNotNull(selector, nameof(selector)); 15 | return SelectImpl(source, selector); 16 | } 17 | 18 | private static IEnumerable SelectImpl( 19 | this IEnumerable source, 20 | Func selector) 21 | { 22 | foreach (TSource item in source) 23 | { 24 | yield return selector(item); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter02/GenericMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 2.5")] 8 | class GenericMethod 9 | { 10 | public static List CopyAtMost(List input, int maxElements) 11 | { 12 | int actualCount = Math.Min(input.Count, maxElements); 13 | List ret = new List(actualCount); 14 | for (int i = 0; i < actualCount; i++) 15 | { 16 | ret.Add(input[i]); 17 | } 18 | return ret; 19 | } 20 | 21 | static void Main() 22 | { 23 | List numbers = new List(); 24 | numbers.Add(5); 25 | numbers.Add(10); 26 | numbers.Add(20); 27 | 28 | List firstTwo = CopyAtMost(numbers, 2); 29 | Console.WriteLine(firstTwo.Count); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter02/NamesWithList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.ComponentModel; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.4")] 9 | public class NamesWithList 10 | { 11 | static List GenerateNames() 12 | { 13 | List names = new List(); 14 | names.Add("Gamma"); 15 | names.Add("Vlissides"); 16 | names.Add("Johnson"); 17 | names.Add("Helm"); 18 | return names; 19 | } 20 | 21 | static void PrintNames(List names) 22 | { 23 | foreach (string name in names) 24 | { 25 | Console.WriteLine(name); 26 | } 27 | } 28 | 29 | static void Main() 30 | { 31 | List names = GenerateNames(); 32 | PrintNames(names); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter10/SwitchOnEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | using static System.Net.HttpStatusCode; 5 | namespace Chapter10 6 | { 7 | class SwitchOnEnum 8 | { 9 | public void HandleResponse(HttpWebResponse response) 10 | { 11 | switch (response.StatusCode) 12 | { 13 | case OK: 14 | Console.WriteLine("Everything is fine"); 15 | break; 16 | case TemporaryRedirect: 17 | case Redirect: 18 | case RedirectMethod: 19 | Console.WriteLine("We were redirected"); 20 | break; 21 | case NotFound: 22 | Console.WriteLine("Couldn't find the content"); 23 | break; 24 | default: 25 | Console.WriteLine("Don't really know..."); 26 | break; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter14/SelectWithLocalMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Chapter14 5 | { 6 | internal static class SelectWithLocalMethods 7 | { 8 | public static IEnumerable Select( 9 | this IEnumerable source, 10 | Func selector) 11 | { 12 | Preconditions.CheckNotNull(source, nameof(source)); 13 | Preconditions.CheckNotNull(selector, nameof(selector)); 14 | return SelectImpl(source, selector); 15 | 16 | IEnumerable SelectImpl( 17 | IEnumerable validatedSource, 18 | Func validatedSelector) 19 | { 20 | foreach (TSource item in validatedSource) 21 | { 22 | yield return validatedSelector(item); 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter02/LineReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.18")] 9 | class LineReader 10 | { 11 | static IEnumerable ReadLines(string path) 12 | { 13 | using (TextReader reader = File.OpenText(path)) 14 | { 15 | string line; 16 | while ((line = reader.ReadLine()) != null) 17 | { 18 | yield return line; 19 | } 20 | } 21 | } 22 | 23 | static void Main() 24 | { 25 | // Adjust the path if you're not running it from the directory 26 | // containing the executable... 27 | foreach (string line in ReadLines("../../../Program.cs")) 28 | { 29 | Console.WriteLine(line); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter02/NamesWithStringCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Specialized; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 2.3")] 8 | public class NamesWithStringCollection 9 | { 10 | static StringCollection GenerateNames() 11 | { 12 | StringCollection names = new StringCollection(); 13 | names.Add("Gamma"); 14 | names.Add("Vlissides"); 15 | names.Add("Johnson"); 16 | names.Add("Helm"); 17 | return names; 18 | } 19 | 20 | static void PrintNames(StringCollection names) 21 | { 22 | foreach (string name in names) 23 | { 24 | Console.WriteLine(name); 25 | } 26 | } 27 | 28 | static void Main() 29 | { 30 | StringCollection names = GenerateNames(); 31 | PrintNames(names); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter04/DyanamicOverloadResolution.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter04 5 | { 6 | [Description("Listing 4.3")] 7 | class DyanamicOverloadResolution 8 | { 9 | static void SampleMethod(int value) 10 | { 11 | Console.WriteLine("Method with int parameter"); 12 | } 13 | 14 | static void SampleMethod(decimal value) 15 | { 16 | Console.WriteLine("Method with decimal parameter"); 17 | } 18 | 19 | static void SampleMethod(object value) 20 | { 21 | Console.WriteLine("Method with object parameter"); 22 | } 23 | 24 | static void CallMethod(dynamic d) 25 | { 26 | SampleMethod(d); 27 | } 28 | 29 | static void Main() 30 | { 31 | CallMethod(10); 32 | CallMethod(10.5m); 33 | CallMethod(10L); 34 | CallMethod("text"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter11/StructuralComparisons.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter11 6 | { 7 | [Description("Listing 11.10")] 8 | class StructuralComparisons 9 | { 10 | static void Main() 11 | { 12 | var Ab = ("A", "b"); 13 | var aB = ("a", "B"); 14 | var aa = ("a", "a"); 15 | var ba = ("b", "a"); 16 | 17 | Compare(Ab, aB); 18 | Compare(aB, aa); 19 | Compare(aB, ba); 20 | } 21 | 22 | static void Compare(T x, T y) 23 | where T : IStructuralEquatable, IStructuralComparable 24 | { 25 | var comparison = x.CompareTo(y, StringComparer.OrdinalIgnoreCase); 26 | var equal = x.Equals(y, StringComparer.OrdinalIgnoreCase); 27 | 28 | Console.WriteLine( 29 | $"{x} and {y} - comparison: {comparison}; equal: {equal}"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter02/ExpandedForEach.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.12")] 9 | class ExpandedForEach 10 | { 11 | static IEnumerable CreateSimpleIterator() 12 | { 13 | yield return 10; 14 | for (int i = 0; i < 3; i++) 15 | { 16 | yield return i; 17 | } 18 | yield return 20; 19 | } 20 | 21 | static void Main() 22 | { 23 | IEnumerable enumerable = CreateSimpleIterator(); 24 | using (IEnumerator enumerator = enumerable.GetEnumerator()) 25 | { 26 | while (enumerator.MoveNext()) 27 | { 28 | int value = enumerator.Current; 29 | Console.WriteLine(value); 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter13/InParameterSideEffects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.13")] 7 | class InParameterSideEffects 8 | { 9 | static void InParameter(in int p, Action action) 10 | { 11 | Console.WriteLine("Start of InParameter method"); 12 | Console.WriteLine($"p = {p}"); 13 | action(); 14 | Console.WriteLine($"p = {p}"); 15 | } 16 | 17 | static void ValueParameter(int p, Action action) 18 | { 19 | Console.WriteLine("Start of ValueParameter method"); 20 | Console.WriteLine($"p = {p}"); 21 | action(); 22 | Console.WriteLine($"p = {p}"); 23 | } 24 | 25 | static void Main() 26 | { 27 | int x = 10; 28 | InParameter(x, () => x++); 29 | 30 | int y = 10; 31 | ValueParameter(y, () => y++); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter12/FibonacciSwitch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.17")] 7 | class FibonacciSwitch 8 | { 9 | static void Main() 10 | { 11 | for (int i = 0; i < 10; i++) 12 | { 13 | Console.WriteLine($"Fib({i}) = {Fib(i)}"); 14 | } 15 | } 16 | 17 | // Note: this is a really inefficient way of computing a Fibonacci number, 18 | // but it's a good example of pattern matching. See chapter 9 for 19 | // more efficient approaches. 20 | static int Fib(int n) 21 | { 22 | switch (n) 23 | { 24 | case 0: return 0; 25 | case 1: return 1; 26 | case var _ when n > 1: return Fib(n - 2) + Fib(n - 1); 27 | default: throw new ArgumentOutOfRangeException(nameof(n), "Input must be non-negative"); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter09/SqlInjection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Data.SqlClient; 4 | 5 | namespace Chapter09 6 | { 7 | [Description("Listing 9.7")] 8 | class SqlInjection 9 | { 10 | static void Main() 11 | { 12 | var connectionString = "not a real database"; 13 | int userId = 15; // Determined elsewhere. Assume this is valid. 14 | var tag = Console.ReadLine(); 15 | using (var conn = new SqlConnection(connectionString)) 16 | { 17 | conn.Open(); 18 | string sql = $@"SELECT Description FROM Entries 19 | WHERE Tag='{tag}' AND UserId={userId}"; 20 | using (var command = new SqlCommand(sql, conn)) 21 | { 22 | using (var reader = command.ExecuteReader()) 23 | { 24 | // Use the data 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter04/SimpleDynamicExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Dynamic; 4 | 5 | namespace Chapter04 6 | { 7 | class SimpleDynamicExample : DynamicObject 8 | { 9 | public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 10 | { 11 | Console.WriteLine("Invoked: {0}({1})", binder.Name, string.Join(", ", args)); 12 | result = null; 13 | return true; 14 | } 15 | 16 | public override bool TryGetMember(GetMemberBinder binder, out object result) 17 | { 18 | result = "Fetched: " + binder.Name; 19 | return true; 20 | } 21 | } 22 | 23 | [Description("Listing 4.7")] 24 | class SimpleDynamicExampleCall 25 | { 26 | static void Main() 27 | { 28 | dynamic example = new SimpleDynamicExample(); 29 | example.CallSomeMethod("x", 10); 30 | Console.WriteLine(example.SomeProperty); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter02/GenericCounter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | class GenericCounter 7 | { 8 | private static int value; 9 | 10 | static GenericCounter() 11 | { 12 | Console.WriteLine("Initializing counter for {0}", typeof(T)); 13 | } 14 | 15 | public static void Increment() 16 | { 17 | value++; 18 | } 19 | 20 | public static void Display() 21 | { 22 | Console.WriteLine("Counter for {0}: {1}", typeof(T), value); 23 | } 24 | } 25 | 26 | [Description("Listing 2.8")] 27 | class GenericCounterDemo 28 | { 29 | static void Main() 30 | { 31 | GenericCounter.Increment(); 32 | GenericCounter.Increment(); 33 | GenericCounter.Display(); 34 | GenericCounter.Display(); 35 | GenericCounter.Increment(); 36 | GenericCounter.Display(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter05/UnsafeCodeInAsyncMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.3")] 8 | class UnsafeCodeInAsyncMethod 9 | { 10 | static void Main() 11 | { 12 | DelayWithResultOfUnsafeCode("Some text").GetAwaiter().GetResult(); 13 | } 14 | 15 | static async Task DelayWithResultOfUnsafeCode(string text) 16 | { 17 | int total = 0; 18 | unsafe 19 | { 20 | fixed (char* textPointer = text) 21 | { 22 | char* p = textPointer; 23 | while (*p != 0) 24 | { 25 | total += *p; 26 | p++; 27 | } 28 | } 29 | } 30 | Console.WriteLine("Delaying for " + total + "ms"); 31 | await Task.Delay(total); 32 | Console.WriteLine("Delay complete"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter13/GenerateRandomString4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | /* TODO: Uncomment this when the framework supports it. 5 | namespace Chapter13 6 | { 7 | [Description("Listing 13.23")] 8 | class GenerateRandomString4 9 | { 10 | static string Generate(string alphabet, Random random, int length) => 11 | string.Create(length, (alphabet, random), (span, state) => 12 | { 13 | var alphabet2 = state.alphabet; 14 | var random2 = state.random; 15 | for (int i = 0; i < span.Length; i++) 16 | { 17 | span[i] = alphabet2[random2.Next(alphabet2.Length)]; 18 | } 19 | }); 20 | 21 | static void Main() 22 | { 23 | string alphabet = "abcdefghijklmnopqrstuvwxyz"; 24 | Random random = new Random(); 25 | Console.WriteLine(Generate(alphabet, random, 10)); 26 | Console.WriteLine(Generate(alphabet, random, 20)); 27 | } 28 | } 29 | } 30 | */ 31 | -------------------------------------------------------------------------------- /Chapter10/ConcurrentDictionaryCollectionInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Chapter10.Extensions 9 | { 10 | public static class DictionaryExtensions 11 | { 12 | public static void Add( 13 | this IDictionary dictionary, 14 | TKey key, TValue value) 15 | { 16 | dictionary.Add(key, value); 17 | } 18 | } 19 | } 20 | 21 | namespace Chapter10 22 | { 23 | using System.ComponentModel; 24 | using static Chapter10.Extensions.DictionaryExtensions; 25 | 26 | [Description("Listing 10.11")] 27 | class ConcurrentDictionaryCollectionInitializer 28 | { 29 | static void Main() 30 | { 31 | var dictionary = new ConcurrentDictionary 32 | { 33 | { "x", 10 }, 34 | { "y", 20 } 35 | }; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodVariableCapture2Equivalent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | [Description("Listing 14.5")] 7 | class LocalMethodVariableCapture2Equivalent 8 | { 9 | struct OuterScope 10 | { 11 | public int hour; 12 | } 13 | 14 | struct InnerScope 15 | { 16 | public int minute; 17 | } 18 | 19 | static void Main() 20 | { 21 | DateTime now = DateTime.UtcNow; 22 | OuterScope outer = new OuterScope(); 23 | outer.hour = now.Hour; 24 | if (outer.hour > 5) 25 | { 26 | InnerScope inner = new InnerScope(); 27 | inner.minute = now.Minute; 28 | PrintValues(ref outer, ref inner); 29 | } 30 | } 31 | 32 | static void PrintValues(ref OuterScope outer, ref InnerScope inner) 33 | { 34 | Console.WriteLine($"hour = {outer.hour}; minute = {inner.minute}"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/NullableAddressFix3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.6")] 7 | class NullableAddressFix3 8 | { 9 | public class Customer 10 | { 11 | public string Name { get; set; } 12 | public Address? Address { get; set; } 13 | 14 | public Customer(string name) => 15 | Name = name; 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | 22 | public Address(string country) => 23 | Country = country; 24 | } 25 | 26 | static void Main() 27 | { 28 | Customer customer = new Customer("Jon"); 29 | if (customer.Address != null) 30 | { 31 | Console.WriteLine(customer.Address.Country); 32 | } 33 | else 34 | { 35 | Console.WriteLine("(Address unknown)"); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter14/LocalMethodUsingThisInStruct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | public struct SimpleValue 6 | { 7 | public int Value { get; } 8 | 9 | public SimpleValue(int value) => this.Value = value; 10 | 11 | public void PrintAndReplace(int newValue) 12 | { 13 | PrintAndReplaceImpl(ref this); 14 | 15 | void PrintAndReplaceImpl(ref SimpleValue _this) 16 | { 17 | // Using this instead of _this causes a compile-time error 18 | Console.WriteLine($"Old value: {_this.Value}"); 19 | _this = new SimpleValue(newValue); 20 | } 21 | } 22 | } 23 | 24 | public class LocalMethodUsingThisInStruct 25 | { 26 | static void Main() 27 | { 28 | var simpleValue = new SimpleValue(10); 29 | Console.WriteLine(simpleValue.Value); // 10 30 | simpleValue.PrintAndReplace(20); // Prints "Old value: 10" 31 | Console.WriteLine(simpleValue.Value); // 20 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter14/OutVarInConstructorInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter14 5 | { 6 | class ParsedText 7 | { 8 | public string Text { get; } 9 | public bool Valid { get; } 10 | 11 | protected ParsedText(string text, bool valid) 12 | { 13 | Text = text; 14 | Valid = valid; 15 | } 16 | } 17 | 18 | class ParsedInt32 : ParsedText 19 | { 20 | public int? Value { get; } 21 | 22 | public ParsedInt32(string text) : base(text, int.TryParse(text, out int parseResult)) 23 | { 24 | Value = Valid ? parseResult : (int?) null; 25 | } 26 | 27 | public override string ToString() => $"Text: {Text}; Valid: {Valid}; Value: {Value}"; 28 | } 29 | 30 | [Description("Listing 14.10")] 31 | class OutVarInConstructorInitializer 32 | { 33 | static void Main() 34 | { 35 | Console.WriteLine(new ParsedInt32("bad")); 36 | Console.WriteLine(new ParsedInt32("123")); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/NullableAddressFix2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.5")] 7 | class NullableAddressFix2 8 | { 9 | public class Customer 10 | { 11 | public string Name { get; set; } 12 | public Address? Address { get; set; } 13 | 14 | public Customer(string name) => 15 | Name = name; 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | 22 | public Address(string country) => 23 | Country = country; 24 | } 25 | 26 | static void Main() 27 | { 28 | Customer customer = new Customer("Jon"); 29 | Address? address = customer.Address; 30 | if (address != null) 31 | { 32 | Console.WriteLine(address.Country); 33 | } 34 | else 35 | { 36 | Console.WriteLine("(Address unknown)"); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter11/FibonacciWithGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.7")] 9 | class FibonacciWithGenerator 10 | { 11 | static void Main() 12 | { 13 | var fibonacci = GenerateSequence( 14 | (current: 0, next: 1), 15 | pair => (pair.next, pair.current + pair.next), 16 | pair => pair.current); 17 | foreach (var value in fibonacci.Take(10)) 18 | { 19 | Console.WriteLine(value); 20 | } 21 | } 22 | 23 | static IEnumerable GenerateSequence( 24 | TState seed, 25 | Func generator, 26 | Func resultSelector) 27 | { 28 | var state = seed; 29 | while (true) 30 | { 31 | yield return resultSelector(state); 32 | state = generator(state); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter02/DecompilationExampleOriginal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter02 7 | { 8 | [Description("Listing 2.19")] 9 | class DecompilationExampleOriginal 10 | { 11 | public static IEnumerable GenerateIntegers(int count) 12 | { 13 | try 14 | { 15 | for (int i = 0; i < count; i++) 16 | { 17 | Console.WriteLine("Yielding {0}", i); 18 | yield return i; 19 | int doubled = i * 2; 20 | Console.WriteLine("Yielding {0}", doubled); 21 | yield return doubled; 22 | } 23 | } 24 | finally 25 | { 26 | Console.WriteLine("In finally block"); 27 | } 28 | } 29 | 30 | static void Main() 31 | { 32 | foreach (int value in GenerateIntegers(5)) 33 | { 34 | Console.WriteLine(value); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter12/DateTimeDeconstruction2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter12 5 | { 6 | [Description("Listing 12.9")] 7 | static class DateTimeDeconstruction2 8 | { 9 | static void Deconstruct( 10 | this DateTime dateTime, 11 | out int year, out int month, out int day) => 12 | (year, month, day) = (dateTime.Year, dateTime.Month, dateTime.Day); 13 | 14 | static void Deconstruct( 15 | this DateTime dateTime, 16 | out int year, out int month, out int day, 17 | out int hour, out int minute, out int second) => 18 | (year, month, day, hour, minute, second) = 19 | (dateTime.Year, dateTime.Month, dateTime.Day, 20 | dateTime.Hour, dateTime.Minute, dateTime.Second); 21 | 22 | static void Main() 23 | { 24 | DateTime birthday = new DateTime(1976, 6, 19); 25 | DateTime now = DateTime.UtcNow; 26 | 27 | var (year, month, day, hour, minute, second) = now; 28 | (year, month, day) = birthday; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/AsyncDisposal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.16")] 8 | class AsyncDisposal 9 | { 10 | class AsyncResource : IAsyncDisposable 11 | { 12 | public async ValueTask DisposeAsync() 13 | { 14 | Console.WriteLine("Disposing asynchronously..."); 15 | await Task.Delay(2000); 16 | Console.WriteLine("... done"); 17 | } 18 | 19 | public async Task PerformWorkAsync() 20 | { 21 | Console.WriteLine("Performing work asynchronously..."); 22 | await Task.Delay(2000); 23 | Console.WriteLine("... done"); 24 | } 25 | } 26 | 27 | async static Task Main() 28 | { 29 | await using (var resource = new AsyncResource()) 30 | { 31 | await resource.PerformWorkAsync(); 32 | } 33 | Console.WriteLine("After the using await statement"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/NullableAddress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace NullableReferences 5 | { 6 | [Description("Listing 15.3")] 7 | class NullableAddress 8 | { 9 | public class Customer 10 | { 11 | public string Name { get; set; } 12 | public Address? Address { get; set; } 13 | 14 | public Customer(string name) => 15 | Name = name; 16 | } 17 | 18 | public class Address 19 | { 20 | public string Country { get; set; } 21 | 22 | public Address(string country) => 23 | Country = country; 24 | } 25 | 26 | static void Main() 27 | { 28 | Customer customer = new Customer("Jon"); 29 | // Suppressed to avoid it being constantly listed, but the intention of this listing 30 | // is to show that it *is* shown as a warning... comment out the pragma to see the warning. 31 | #pragma warning disable CS8602 // Possible dereference of a null reference. 32 | Console.WriteLine(customer.Address.Country); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter13/SafeInParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter13 5 | { 6 | [Description("Listing 13.14")] 7 | class SafeInParameters 8 | { 9 | public static double PublicMethod(LargeStruct first, LargeStruct second) 10 | { 11 | double firstResult = PrivateMethod(in first); 12 | double secondResult = PrivateMethod(in second); 13 | return firstResult + secondResult; 14 | } 15 | 16 | private static double PrivateMethod(in LargeStruct input) 17 | { 18 | double scale = GetScale(in input); 19 | return (input.X + input.Y + input.Z) * scale; 20 | } 21 | 22 | private static double GetScale(in LargeStruct input) => 23 | input.Weight * input.Score; 24 | 25 | static void Main() 26 | { 27 | LargeStruct first = new LargeStruct(1L, 2L, 3L, 4.1, 5.2); 28 | LargeStruct second = new LargeStruct(6L, 7L, 8L, 9.3, 10.4); 29 | 30 | double result = PublicMethod(first, second); 31 | Console.WriteLine(result); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/DeconstructionPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter15 6 | { 7 | class DeconstructionPattern 8 | { 9 | static void Main() 10 | { 11 | Rectangle r = new Rectangle(10, 5); 12 | Triangle t = new Triangle(3, 4, 5); 13 | Circle c = new Circle(10); 14 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 15 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 16 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 17 | } 18 | 19 | static double Perimeter(Shape shape) => shape switch 20 | { 21 | null => throw new ArgumentNullException(nameof(shape)), 22 | Rectangle { Height: var h, Width: var w } => 2 * (h + w), 23 | Circle { Radius: var radius } => 2 * PI * radius, 24 | Triangle (var a, var b, var c) => a + b + c, 25 | _ => throw new ArgumentException( 26 | $"Shape type {shape.GetType()} perimeter unknown", nameof(shape)) 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter12/NumericBounds.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter12 7 | { 8 | [Description("Listing 12.18")] 9 | class NumericBounds 10 | { 11 | static void Main() 12 | { 13 | CheckBounds(10); 14 | CheckBounds(10000); 15 | CheckBounds(10000L); 16 | CheckBounds(100000L); 17 | CheckBounds(-10000L); 18 | } 19 | 20 | static void CheckBounds(object input) 21 | { 22 | switch (input) 23 | { 24 | case int x when x > 1000: 25 | case long y when y > 10000L: 26 | Console.WriteLine("Value is too large"); 27 | break; 28 | case int x when x < -1000: 29 | case long y when y < -10000L: 30 | Console.WriteLine("Value is too low"); 31 | break; 32 | default: 33 | Console.WriteLine("Value is in range"); 34 | break; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter09Net40/FormattableString.cs: -------------------------------------------------------------------------------- 1 | //using System.Globalization; 2 | 3 | using System.ComponentModel; 4 | 5 | namespace System 6 | { 7 | [Description("Listing 9.10 (second half)")] 8 | internal class FormattableString : IFormattable 9 | { 10 | public string Format { get; } 11 | private readonly object[] arguments; 12 | 13 | internal FormattableString(string format, object[] arguments) 14 | { 15 | Format = format; 16 | this.arguments = arguments; 17 | } 18 | 19 | public object GetArgument(int index) => arguments[index]; 20 | public object[] GetArguments() => arguments; 21 | public int ArgumentCount => arguments.Length; 22 | public static string Invariant(FormattableString formattable) => 23 | formattable?.ToString(Globalization.CultureInfo.InvariantCulture); 24 | public string ToString(IFormatProvider formatProvider) => 25 | string.Format(formatProvider, Format, arguments); 26 | public string ToString( 27 | string ignored, IFormatProvider formatProvider) => 28 | ToString(formatProvider); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter07/CallerInfoConstructors.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Chapter07 6 | { 7 | [Description("Listing 7.7")] 8 | class CallerInfoConstructors 9 | { 10 | public abstract class BaseClass 11 | { 12 | protected BaseClass( 13 | [CallerFilePath] string file = "Unspecified file", 14 | [CallerLineNumber] int line = -1, 15 | [CallerMemberName] string member = "Unspecified member") 16 | { 17 | Console.WriteLine("{0}:{1} - {2}", file, line, member); 18 | } 19 | } 20 | 21 | public class Derived1 : BaseClass { } 22 | 23 | public class Derived2 : BaseClass 24 | { 25 | internal Derived2() { } 26 | } 27 | 28 | public class Derived3 : BaseClass 29 | { 30 | internal Derived3() : base() {} 31 | } 32 | 33 | static void Main() 34 | { 35 | var d1 = new Derived1(); 36 | var d2 = new Derived2(); 37 | var d3 = new Derived3(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter04Com/SaveFileOld.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Word; 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter04Com 6 | { 7 | [Description("Listing 4.16")] 8 | class SaveFileOld 9 | { 10 | static void Main() 11 | { 12 | object missing = Type.Missing; 13 | 14 | Application app = new Application { Visible = true }; 15 | Document doc = app.Documents.Add(ref missing, ref missing, ref missing, ref missing); 16 | Paragraph para = doc.Paragraphs.Add(ref missing); 17 | para.Range.Text = "Awkward old code"; 18 | 19 | object fileName = "demo1.docx"; 20 | doc.SaveAs2(ref fileName, ref missing, 21 | ref missing, ref missing, ref missing, 22 | ref missing, ref missing, ref missing, 23 | ref missing, ref missing, ref missing, 24 | ref missing, ref missing, ref missing, 25 | ref missing, ref missing); 26 | 27 | doc.Close(ref missing, ref missing, ref missing); 28 | app.Application.Quit(ref missing, ref missing, ref missing); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter02/PartialDemo2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Chapter02 5 | { 6 | [Description("Listing 2.23")] 7 | class PartialDemo2 8 | { 9 | partial class PartialMethodsDemo 10 | { 11 | public PartialMethodsDemo() 12 | { 13 | OnConstruction(); 14 | } 15 | 16 | public override string ToString() 17 | { 18 | string ret = "Original return value"; 19 | CustomizeToString(ref ret); 20 | return ret; 21 | } 22 | 23 | partial void OnConstruction(); 24 | partial void CustomizeToString(ref string text); 25 | } 26 | 27 | partial class PartialMethodsDemo 28 | { 29 | partial void CustomizeToString(ref string text) 30 | { 31 | text += " - customized!"; 32 | } 33 | } 34 | 35 | static void Main() 36 | { 37 | PartialMethodsDemo demo = new PartialMethodsDemo(); 38 | string text = demo.ToString(); 39 | Console.WriteLine(text); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter03/CapturingMultipleInstantiationsImpl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 3.9")] 8 | class CapturingMultipleInstantiationsImpl 9 | { 10 | private class LambdaContext 11 | { 12 | public string text; 13 | 14 | public void Method() 15 | { 16 | Console.WriteLine(text); 17 | } 18 | } 19 | 20 | static List CreateActions() 21 | { 22 | List actions = new List(); 23 | for (int i = 0; i < 5; i++) 24 | { 25 | LambdaContext context = new LambdaContext(); 26 | context.text = string.Format("message {0}", i); 27 | actions.Add(context.Method); 28 | } 29 | return actions; 30 | } 31 | 32 | static void Main() 33 | { 34 | List actions = CreateActions(); 35 | foreach (Action action in actions) 36 | { 37 | action(); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter03/CapturingMultipleScopes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter03 6 | { 7 | [Description("Listing 3.10")] 8 | class CapturingMultipleScopes 9 | { 10 | static List CreateCountingActions() 11 | { 12 | List actions = new List(); 13 | int outerCounter = 0; 14 | for (int i = 0; i < 2; i++) 15 | { 16 | int innerCounter = 0; 17 | Action action = () => 18 | { 19 | Console.WriteLine( 20 | "Outer: {0}; Inner: {1}", 21 | outerCounter, innerCounter); 22 | outerCounter++; 23 | innerCounter++; 24 | }; 25 | actions.Add(action); 26 | } 27 | return actions; 28 | } 29 | 30 | static void Main() 31 | { 32 | List actions = CreateCountingActions(); 33 | actions[0](); 34 | actions[0](); 35 | actions[1](); 36 | actions[1](); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter11/HighScoreDisplayWithTuples.cs: -------------------------------------------------------------------------------- 1 | using NodaTime; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.12")] 9 | class HighScoreDisplayWithTuples 10 | { 11 | static void DisplayHighScoreForDate(LocalDate date) 12 | { 13 | var filteredGames = Game.AllGames.Where(game => game.Date == date); 14 | (string player, int score) highest = (null, -1); 15 | foreach (var game in filteredGames) 16 | { 17 | if (game.Score > highest.score) 18 | { 19 | highest = (game.PlayerName, game.Score); 20 | } 21 | } 22 | Console.WriteLine(highest.player == null 23 | ? "No games played" 24 | : $"Highest score was {highest.score} by {highest.player}"); 25 | } 26 | 27 | static void Main() 28 | { 29 | DisplayHighScoreForDate(new LocalDate(2018, 5, 30)); 30 | DisplayHighScoreForDate(new LocalDate(2018, 5, 31)); 31 | DisplayHighScoreForDate(new LocalDate(2018, 6, 1)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/PropertyPatterns1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.11")] 8 | class PropertyPatterns1 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) => shape switch 21 | { 22 | null => throw new ArgumentNullException(nameof(shape)), 23 | Rectangle { Height: var h, Width: var w } => 2 * (h + w), 24 | Circle { Radius: var radius } => 2 * PI * radius, 25 | Triangle { SideA: var a, SideB: var b, SideC: var c } => a + b + c, 26 | _ => throw new ArgumentException( 27 | $"Shape type {shape.GetType()} perimeter unknown", nameof(shape)) 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/SwitchExpressionBodiedMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.10")] 8 | class SwitchExpressionBodiedMember 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) => 21 | shape switch 22 | { 23 | null => throw new ArgumentNullException(nameof(shape)), 24 | Rectangle rect => 2 * (rect.Height + rect.Width), 25 | Circle circle => 2 * PI * circle.Radius, 26 | Triangle triangle => triangle.SideA + triangle.SideB + triangle.SideC, 27 | _ => throw new ArgumentException( 28 | $"Shape type {shape.GetType()} perimeter unknown", nameof(shape)) 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter11/HighScoreDisplayWithoutTuples.cs: -------------------------------------------------------------------------------- 1 | using NodaTime; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.11")] 9 | class HighScoreDisplayWithoutTuples 10 | { 11 | static void DisplayHighScoreForDate(LocalDate date) 12 | { 13 | var filteredGames = Game.AllGames.Where(game => game.Date == date); 14 | string highestPlayer = null; 15 | int highestScore = -1; 16 | foreach (var game in filteredGames) 17 | { 18 | if (game.Score > highestScore) 19 | { 20 | highestPlayer = game.PlayerName; 21 | highestScore = game.Score; 22 | } 23 | } 24 | Console.WriteLine(highestPlayer == null 25 | ? "No games played" 26 | : $"Highest score was {highestScore} by {highestPlayer}"); 27 | } 28 | 29 | static void Main() 30 | { 31 | DisplayHighScoreForDate(new LocalDate(2018, 5, 30)); 32 | DisplayHighScoreForDate(new LocalDate(2018, 5, 31)); 33 | DisplayHighScoreForDate(new LocalDate(2018, 6, 1)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/SwitchExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter15 6 | { 7 | [Description("Listing 15.9")] 8 | class SwitchExpression 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) 21 | { 22 | return shape switch 23 | { 24 | null => throw new ArgumentNullException(nameof(shape)), 25 | Rectangle rect => 2 * (rect.Height + rect.Width), 26 | Circle circle => 2 * PI * circle.Radius, 27 | Triangle triangle => triangle.SideA + triangle.SideB + triangle.SideC, 28 | _ => throw new ArgumentException( 29 | $"Shape type {shape.GetType()} perimeter unknown", nameof(shape)) 30 | }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter05/EagerArgumentValidation1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.6a (separate method for implementation)")] 8 | class EagerArgumentValidation1 9 | { 10 | static void Main() 11 | { 12 | MainAsync().GetAwaiter().GetResult(); 13 | } 14 | 15 | // This method is the same as in LazyArgumentValidation; 16 | // only ComputeLengthAsync is different. 17 | static async Task MainAsync() 18 | { 19 | Task task = ComputeLengthAsync(null); 20 | Console.WriteLine("Fetched the task"); 21 | int length = await task; 22 | Console.WriteLine("Length: {0}", length); 23 | } 24 | 25 | static Task ComputeLengthAsync(string text) 26 | { 27 | if (text == null) 28 | { 29 | throw new ArgumentNullException("text"); 30 | } 31 | return ComputeLengthAsyncImpl(text); 32 | } 33 | 34 | static async Task ComputeLengthAsyncImpl(string text) 35 | { 36 | await Task.Delay(500); 37 | return text.Length; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CSharp8/Chapter15/DamnItOperatorValidation.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | 4 | namespace NullableReferences 5 | { 6 | public class DamnItOperatorValidation 7 | { 8 | public class Customer 9 | { 10 | public string Name { get; } 11 | public Address? Address { get; } 12 | 13 | public Customer(string name, Address? address) 14 | { 15 | Name = name ?? throw new ArgumentNullException(nameof(name)); 16 | Address = address; 17 | } 18 | } 19 | 20 | public class Address 21 | { 22 | public string Country { get; } 23 | 24 | public Address(string country) 25 | { 26 | Country = country ?? throw new ArgumentNullException(nameof(country)); 27 | } 28 | } 29 | 30 | [Test] 31 | public void Customer_NameValidation() 32 | { 33 | Address address = new Address("UK"); 34 | Assert.Throws(() => new Customer(null!, address)); 35 | } 36 | 37 | [Test] 38 | public void Address_CountryValidation() 39 | { 40 | Assert.Throws(() => new Address(null!)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter05/AwaitingFailedOperations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Net.Http; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chapter05 8 | { 9 | [Description("Listing 5.4")] 10 | class AwaitingFailedOperations 11 | { 12 | static void Main() 13 | { 14 | var task = FetchFirstSuccessfulAsync(new[] { "http://invalid.csharpindepth.com", "http://csharpindepth.com", "https://manning.com", "https://microsoft.com" }); 15 | var result = task.GetAwaiter().GetResult(); 16 | Console.WriteLine(result.Length); 17 | } 18 | 19 | static async Task FetchFirstSuccessfulAsync(IEnumerable urls) 20 | { 21 | var client = new HttpClient(); 22 | foreach (string url in urls) 23 | { 24 | try 25 | { 26 | return await client.GetStringAsync(url); 27 | } 28 | catch (HttpRequestException exception) 29 | { 30 | Console.WriteLine("Failed to fetch {0}: {1}", url, exception.Message); 31 | } 32 | } 33 | throw new HttpRequestException("No URLs succeeded"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter12/ShapePerimeterWithPatternsIfElse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.13")] 8 | class ShapePerimeterWithPatternsIfElse 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) 21 | { 22 | if (shape == null) 23 | throw new ArgumentNullException(nameof(shape)); 24 | if (shape is Rectangle rect) 25 | return 2 * (rect.Height + rect.Width); 26 | if (shape is Circle circle) 27 | return 2 * PI * circle.Radius; 28 | if (shape is Triangle triangle) 29 | return triangle.SideA + triangle.SideB + triangle.SideC; 30 | throw new ArgumentException($"Shape type {shape.GetType()} perimeter unknown", nameof(shape)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter10/SimpleRetry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading; 4 | 5 | namespace Chapter10 6 | { 7 | [Description("Listing 10.15")] 8 | class SimpleRetry 9 | { 10 | static T Retry(Func operation, int attempts) 11 | { 12 | while (true) 13 | { 14 | try 15 | { 16 | attempts--; 17 | return operation(); 18 | } 19 | catch (Exception e) when (attempts > 0) 20 | { 21 | Console.WriteLine($"Failed: {e}"); 22 | Console.WriteLine($"Attempts left: {attempts}"); 23 | Thread.Sleep(5000); 24 | } 25 | } 26 | } 27 | 28 | static void Main() 29 | { 30 | Func temporamentalCall = () => 31 | { 32 | DateTime utcNow = DateTime.UtcNow; 33 | if (utcNow.Second < 20) 34 | { 35 | throw new Exception("I don't like the start of a minute"); 36 | } 37 | return utcNow; 38 | }; 39 | 40 | var result = Retry(temporamentalCall, 3); 41 | Console.WriteLine(result); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Chapter04/MixedDynamicAndStaticOverloadResolution.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Chapter04 6 | { 7 | class MixedDynamicAndStaticOverloadResolution 8 | { 9 | static void Method(int x, string y) 10 | { 11 | Console.WriteLine("int, string"); 12 | } 13 | 14 | static void Method(int x, object y) 15 | { 16 | Console.WriteLine("int, object"); 17 | } 18 | 19 | static void Method(object x, object y) 20 | { 21 | Console.WriteLine("object, object"); 22 | } 23 | 24 | static void Main() 25 | { 26 | dynamic arg1 = 10; 27 | object arg2 = "text"; 28 | // This calls the second overload - the "int, object" method. 29 | // - The first overload isn't applicable because the *compile-time* type of arg2 is 30 | // used. Even though this is a dynamically-bound call, the second argument has a 31 | // static type of "object", so that's used in overload resolution. 32 | // - The third overload isn't used because the second overload is more specific: 33 | // the execution-time type of arg1 is used because it's dynamic. 34 | Method(arg1, arg2); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter11/MinMax3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.4")] 9 | class MinMax3 10 | { 11 | static void Main() 12 | { 13 | Random rng = new Random(); 14 | var numbers = Enumerable.Range(0, 100).Select(_ => rng.Next(1000)); 15 | var minMax = MinMax(numbers); 16 | Console.WriteLine($"Minimum: {minMax.min}"); 17 | Console.WriteLine($"Maximum: {minMax.max}"); 18 | } 19 | 20 | static (int min, int max) MinMax(IEnumerable source) 21 | { 22 | using (var iterator = source.GetEnumerator()) 23 | { 24 | if (!iterator.MoveNext()) 25 | { 26 | throw new InvalidOperationException("Cannot find min/max of an empty sequence"); 27 | } 28 | var result = (min: iterator.Current, max: iterator.Current); 29 | while (iterator.MoveNext()) 30 | { 31 | result = (Math.Min(result.min, iterator.Current), 32 | Math.Max(result.max, iterator.Current)); 33 | } 34 | return result; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter11/MinMax1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.1")] 9 | class MinMax1 10 | { 11 | static void Main() 12 | { 13 | Random rng = new Random(); 14 | var numbers = Enumerable.Range(0, 100).Select(_ => rng.Next(1000)); 15 | var minMax = MinMax(numbers); 16 | Console.WriteLine($"Minimum: {minMax.min}"); 17 | Console.WriteLine($"Maximum: {minMax.max}"); 18 | } 19 | 20 | static (int min, int max) MinMax(IEnumerable source) 21 | { 22 | using (var iterator = source.GetEnumerator()) 23 | { 24 | if (!iterator.MoveNext()) 25 | { 26 | throw new InvalidOperationException("Cannot find min/max of an empty sequence"); 27 | } 28 | int min = iterator.Current; 29 | int max = iterator.Current; 30 | while (iterator.MoveNext()) 31 | { 32 | min = Math.Min(min, iterator.Current); 33 | max = Math.Max(max, iterator.Current); 34 | } 35 | 36 | return (min, max); 37 | } 38 | 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter11/MinMax2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | 6 | namespace Chapter11 7 | { 8 | [Description("Listing 11.3")] 9 | class MinMax2 10 | { 11 | static void Main() 12 | { 13 | Random rng = new Random(); 14 | var numbers = Enumerable.Range(0, 100).Select(_ => rng.Next(1000)); 15 | var minMax = MinMax(numbers); 16 | Console.WriteLine($"Minimum: {minMax.min}"); 17 | Console.WriteLine($"Maximum: {minMax.max}"); 18 | } 19 | 20 | static (int min, int max) MinMax(IEnumerable source) 21 | { 22 | using (var iterator = source.GetEnumerator()) 23 | { 24 | if (!iterator.MoveNext()) 25 | { 26 | throw new InvalidOperationException("Cannot find min/max of an empty sequence"); 27 | } 28 | var result = (min: iterator.Current, max: iterator.Current); 29 | while (iterator.MoveNext()) 30 | { 31 | result.min = Math.Min(result.min, iterator.Current); 32 | result.max = Math.Max(result.max, iterator.Current); 33 | } 34 | return result; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter03/CapturedVariablesDemo.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable CS0219 // Variable is assigned but its value is never used 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter02 6 | { 7 | [Description("Listing 3.6")] 8 | class CapturedVariablesDemo 9 | { 10 | private string instanceField = "instance field"; 11 | 12 | public Action CreateAction(string methodParameter) 13 | { 14 | string methodLocal = "method local"; 15 | string uncaptured = "uncaptured local"; 16 | 17 | Action action = lambdaParameter => 18 | { 19 | string lambdaLocal = "lambda local"; 20 | Console.WriteLine("Instance field: {0}", instanceField); 21 | Console.WriteLine("Method parameter: {0}", methodParameter); 22 | Console.WriteLine("Method local: {0}", methodLocal); 23 | Console.WriteLine("Lambda parameter: {0}", lambdaParameter); 24 | Console.WriteLine("Lambda local: {0}", lambdaLocal); 25 | }; 26 | return action; 27 | } 28 | 29 | static void Main() 30 | { 31 | var demo = new CapturedVariablesDemo(); 32 | Action action = demo.CreateAction("method argument"); 33 | action("lambda argument"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter05/AsyncIntro.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | using System.Net.Http; 5 | using System.Windows.Forms; 6 | 7 | namespace Chapter05 8 | { 9 | [Description("Listing 5.1")] 10 | public class AsyncIntro : Form 11 | { 12 | private static readonly HttpClient client = new HttpClient(); 13 | private readonly Label label; 14 | private readonly Button button; 15 | 16 | public AsyncIntro() 17 | { 18 | label = new Label 19 | { 20 | Location = new Point(10, 20), 21 | Text = "Length" 22 | }; 23 | button = new Button 24 | { 25 | Location = new Point(10, 50), 26 | Text = "Click" 27 | }; 28 | button.Click += DisplayWebSiteLength; 29 | AutoSize = true; 30 | Controls.Add(label); 31 | Controls.Add(button); 32 | } 33 | 34 | async void DisplayWebSiteLength(object sender, EventArgs e) 35 | { 36 | label.Text = "Fetching..."; 37 | string text = await client.GetStringAsync("http://csharpindepth.com"); 38 | label.Text = text.Length.ToString(); 39 | } 40 | 41 | static void Main() 42 | { 43 | Application.Run(new AsyncIntro()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter12/GenericTypeCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.15")] 8 | class GenericTypeCase 9 | { 10 | static void Main() 11 | { 12 | var shapes = new List 13 | { 14 | new Circle(15.2), 15 | new Rectangle(20.3, 10.2), 16 | new Triangle(12.1, 15.9, 13.8) 17 | }; 18 | 19 | DisplayShapes(shapes); 20 | DisplayShapes(new List { new Circle(10.2), new Circle(15.2) }); 21 | } 22 | 23 | static void DisplayShapes(List shapes) where T : Shape 24 | { 25 | foreach (T shape in shapes) 26 | { 27 | switch (shape) 28 | { 29 | case Circle c: 30 | Console.WriteLine($"Circle radius {c.Radius}"); 31 | break; 32 | case Rectangle r: 33 | Console.WriteLine($"Rectangle {r.Width} x {r.Height}"); 34 | break; 35 | case Triangle t: 36 | Console.WriteLine($"Triangle sides {t.SideA}, {t.SideB}, {t.SideC}"); 37 | break; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter05/EagerArgumentValidation2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.6b (anonyous async function)")] 8 | class EagerArgumentValidation2 9 | { 10 | static void Main() 11 | { 12 | MainAsync().GetAwaiter().GetResult(); 13 | } 14 | 15 | // This method is the same as in LazyArgumentValidation; 16 | // only ComputeLengthAsync is different. 17 | static async Task MainAsync() 18 | { 19 | Task task = ComputeLengthAsync(null); 20 | Console.WriteLine("Fetched the task"); 21 | int length = await task; 22 | Console.WriteLine("Length: {0}", length); 23 | } 24 | 25 | static Task ComputeLengthAsync(string text) 26 | { 27 | if (text == null) 28 | { 29 | throw new ArgumentNullException("text"); 30 | } 31 | // This could just be a Func> using 32 | // text, but that would be less efficient than passing 33 | // the value in directly. 34 | Func> impl = async t => 35 | { 36 | await Task.Delay(500); 37 | return text.Length; 38 | }; 39 | return impl(text); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter12/Shape.cs: -------------------------------------------------------------------------------- 1 | using static System.Math; 2 | 3 | namespace Chapter12 4 | { 5 | public abstract class Shape 6 | { 7 | public abstract double Area { get; } 8 | } 9 | 10 | public class Rectangle : Shape 11 | { 12 | public double Width { get; } 13 | public double Height { get; } 14 | public override double Area => Width * Height; 15 | 16 | public Rectangle(double width, double height) => (Width, Height) = (width, height); 17 | } 18 | 19 | public class Triangle : Shape 20 | { 21 | public double SideA { get; } 22 | public double SideB { get; } 23 | public double SideC { get; } 24 | 25 | public override double Area 26 | { 27 | get 28 | { 29 | // Heron's formula... see https://en.wikipedia.org/wiki/Heron%27s_formula 30 | double s = (SideA + SideB + SideC) / 2; 31 | return Sqrt(s * (s - SideA) * (s - SideB) * (s - SideC)); 32 | } 33 | } 34 | 35 | public Triangle(double sideA, double sideB, double sideC) => 36 | (SideA, SideB, SideC) = (sideA, sideB, sideC); 37 | } 38 | 39 | public class Circle : Shape 40 | { 41 | public double Radius { get; } 42 | 43 | public override double Area => PI * Radius * Radius; 44 | 45 | public Circle(double radius) => Radius = radius; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Chapter12/ShapePerimeterWithPatternsSwitchCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.11")] 8 | class ShapePerimeterWithPatternsSwitchCase 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) 21 | { 22 | switch (shape) 23 | { 24 | case null: 25 | throw new ArgumentNullException(nameof(shape)); 26 | case Rectangle rect: 27 | return 2 * (rect.Height + rect.Width); 28 | case Circle circle: 29 | return 2 * PI * circle.Radius; 30 | case Triangle triangle: 31 | return triangle.SideA + triangle.SideB + triangle.SideC; 32 | default: 33 | throw new ArgumentException($"Shape type {shape.GetType()} perimeter unknown", nameof(shape)); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter12/ShapePerimeterBeforePatterns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using static System.Math; 4 | 5 | namespace Chapter12 6 | { 7 | [Description("Listing 12.10")] 8 | class ShapePerimeterBeforePatterns 9 | { 10 | static void Main() 11 | { 12 | Rectangle r = new Rectangle(10, 5); 13 | Triangle t = new Triangle(3, 4, 5); 14 | Circle c = new Circle(10); 15 | Console.WriteLine($"Perimeter of rectangle: {Perimeter(r)}"); 16 | Console.WriteLine($"Perimeter of triangle: {Perimeter(t)}"); 17 | Console.WriteLine($"Perimeter of circle: {Perimeter(c)}"); 18 | } 19 | 20 | static double Perimeter(Shape shape) 21 | { 22 | if (shape == null) 23 | throw new ArgumentNullException(nameof(shape)); 24 | Rectangle rect = shape as Rectangle; 25 | if (rect != null) 26 | return 2 * (rect.Height + rect.Width); 27 | Circle circle = shape as Circle; 28 | if (circle != null) 29 | return 2 * PI * circle.Radius; 30 | Triangle triangle = shape as Triangle; 31 | if (triangle != null) 32 | return triangle.SideA + triangle.SideB + triangle.SideC; 33 | throw new ArgumentException($"Shape type {shape.GetType()} perimeter unknown", nameof(shape)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter14/OverloadResolution.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter14 4 | { 5 | class OverloadResolution 6 | { 7 | static void Method1(object x) where T : struct => 8 | Console.WriteLine($"{typeof(T)} is a struct"); 9 | 10 | static void Method1(string x) where T : class => 11 | Console.WriteLine($"{typeof(T)} is a reference type"); 12 | 13 | static void Method2(object x) => 14 | Console.WriteLine("Static method"); 15 | 16 | void Method2(string x) => 17 | Console.WriteLine("Instance method"); 18 | 19 | void Method3(object x) => 20 | Console.WriteLine("Instance method"); 21 | 22 | static void Method3(string x) => 23 | Console.WriteLine("Static method"); 24 | 25 | static void Main() 26 | { 27 | // Overload with string parameter is better, but int violatesd the "where T : struct" constraint 28 | Method1("text"); 29 | 30 | // Overload with string parameter is better, but we can't call an instance method from a static 31 | // context without providing a reference to value it on. 32 | Method2("text"); 33 | 34 | // Overload with string parameter is better, but we can't call a static method on a reference. 35 | var instance = new OverloadResolution(); 36 | instance.Method3("text"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter05/EagerArgumentValidation3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Threading.Tasks; 4 | 5 | namespace Chapter05 6 | { 7 | [Description("Listing 5.6c (local method)")] 8 | class EagerArgumentValidation3 9 | { 10 | static void Main() 11 | { 12 | MainAsync().GetAwaiter().GetResult(); 13 | } 14 | 15 | // This method is the same as in LazyArgumentValidation; 16 | // only ComputeLengthAsync is different. 17 | static async Task MainAsync() 18 | { 19 | Task task = ComputeLengthAsync(null); 20 | Console.WriteLine("Fetched the task"); 21 | int length = await task; 22 | Console.WriteLine("Length: {0}", length); 23 | } 24 | 25 | static Task ComputeLengthAsync(string text) 26 | { 27 | if (text == null) 28 | { 29 | // If we can use local methods, we can definitely use nameof... 30 | throw new ArgumentNullException(nameof(text)); 31 | } 32 | return Impl(text); 33 | 34 | // This could be a parameterless method, but by passing the 35 | // value in rather than capturing it, the compiler can optimize more. 36 | async Task Impl(string t) 37 | { 38 | await Task.Delay(500); 39 | return t.Length; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter07/OldPropertyNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Text; 5 | 6 | namespace Chapter07 7 | { 8 | class OldPropertyNotifier : INotifyPropertyChanged 9 | { 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | private int firstValue; 12 | public int FirstValue 13 | { 14 | get { return firstValue; } 15 | set 16 | { 17 | if (value != firstValue) 18 | { 19 | firstValue = value; 20 | NotifyPropertyChanged("FirstValue"); 21 | } 22 | } 23 | } 24 | // Other properties with the same pattern 25 | private void NotifyPropertyChanged(string propertyName) 26 | { 27 | PropertyChangedEventHandler handler = PropertyChanged; 28 | if (handler != null) 29 | { 30 | handler(this, new PropertyChangedEventArgs(propertyName)); 31 | } 32 | } 33 | } 34 | 35 | [Description("Listing 7.4")] 36 | class PropertyNotificationBeforeCallerInfo 37 | { 38 | static void Main() 39 | { 40 | var model = new OldPropertyNotifier(); 41 | model.PropertyChanged += (sender, args) => 42 | Console.WriteLine("{0} has changed", args.PropertyName); 43 | model.FirstValue = 10; 44 | model.FirstValue = 20; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Chapter07/NewPropertyNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | 5 | namespace Chapter07 6 | { 7 | class NewPropertyNotifier : INotifyPropertyChanged 8 | { 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | private int firstValue; 11 | public int FirstValue 12 | { 13 | get { return firstValue; } 14 | set 15 | { 16 | if (value != firstValue) 17 | { 18 | firstValue = value; 19 | NotifyPropertyChanged("FirstValue"); 20 | } 21 | } 22 | } 23 | // Other properties with the same pattern 24 | private void NotifyPropertyChanged([CallerMemberName] string propertyName = null) 25 | { 26 | PropertyChangedEventHandler handler = PropertyChanged; 27 | if (handler != null) 28 | { 29 | handler(this, new PropertyChangedEventArgs(propertyName)); 30 | } 31 | } 32 | } 33 | 34 | [Description("Listing 7.5")] 35 | class PropertyNotificationAfterCallerInfo 36 | { 37 | static void Main() 38 | { 39 | var model = new NewPropertyNotifier(); 40 | model.PropertyChanged += (sender, args) => 41 | Console.WriteLine("{0} has changed", args.PropertyName); 42 | model.FirstValue = 10; 43 | model.FirstValue = 20; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter09/LazyEvaluation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Chapter09 4 | { 5 | class LazyEvaluation 6 | { 7 | static void Main() 8 | { 9 | // Never use this code. It's here for amusement, that's all. 10 | string value = "Before"; 11 | FormattableString formattable = $"Current value: {_(() => value)}"; 12 | Console.WriteLine(formattable); 13 | 14 | value = "After"; 15 | Console.WriteLine(formattable); 16 | } 17 | 18 | #pragma warning disable IDE1006 // Naming Styles 19 | static Capture _(Func provider) 20 | #pragma warning restore IDE1006 // Naming Styles 21 | { 22 | return new Capture(provider); 23 | } 24 | } 25 | 26 | class Capture : IFormattable 27 | { 28 | private readonly Func provider; 29 | 30 | public Capture(Func provider) 31 | { 32 | this.provider = provider; 33 | } 34 | 35 | public override String ToString() 36 | { 37 | return base.ToString(); 38 | } 39 | 40 | public String ToString(string format, IFormatProvider formatProvider) 41 | { 42 | object value = provider(); 43 | if (value == null) 44 | { 45 | return ""; 46 | } 47 | var formattable = value as IFormattable; 48 | return formattable == null ? value.ToString() : formattable.ToString(format, formatProvider); 49 | } 50 | } 51 | } 52 | --------------------------------------------------------------------------------