0% found this document useful (0 votes)
110 views793 pages

Csharp Book

This document outlines an introduction to the C# programming language. It covers getting started by creating new projects in Visual Studio, .NET Core and other tools. It then discusses various C# language topics like literals, operators, conditional statements, equality comparisons and the null-coalescing operator across multiple sections and chapters.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
110 views793 pages

Csharp Book

This document outlines an introduction to the C# programming language. It covers getting started by creating new projects in Visual Studio, .NET Core and other tools. It then discusses various C# language topics like literals, operators, conditional statements, equality comparisons and the null-coalescing operator across multiple sections and chapters.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 793

Contents

About ............................................................................................................................................... 1
Chapter 1: Getting started with C# Language .............................................................................. 2
Section 1.1: Creating a new console application (Visual Studio) ............................................................................... 2
Section 1.2: Creating a new project in Visual Studio (console application) and Running it in Debug mode
4
Section 1.3: Creating a new program using .NET Core ............................................................................................. 7
Section 1.4: Creating a new program using Mono ..................................................................................................... 9
Section 1.5: Creating a new query using LinqPad ...................................................................................................... 9
Section 1.6: Creating a new project using Xamarin Studio ......................................................................................12
Chapter 2: Literals .........................................................................................................................18
Section 2.1: uint literals .............................................................................................................................................18
Section 2.2: int literals ...............................................................................................................................................18
Section 2.3: sbyte literals ..........................................................................................................................................18
Section 2.4: decimal literals ......................................................................................................................................18
Section 2.5: double literals ........................................................................................................................................18
Section 2.6: float literals ............................................................................................................................................18
Section 2.7: long literals ............................................................................................................................................18
Section 2.8: ulong literal ...........................................................................................................................................18
Section 2.9: string literals ..........................................................................................................................................19
Section 2.10: char literals .........................................................................................................................................19
Section 2.11: byte literals ..........................................................................................................................................19
Section 2.12: short literal ..........................................................................................................................................19
Section 2.13: ushort literal ........................................................................................................................................19
Section 2.14: bool literals ..........................................................................................................................................19
Chapter 3: Operators ....................................................................................................................20
Section 3.1: Overloadable Operators .......................................................................................................................20
Section 3.2: Overloading equality operators .............................................................................................................21
Section 3.3: Relational Operators .............................................................................................................................22
Section 3.4: Implicit Cast and Explicit Cast Operators .............................................................................................24
Section 3.5: Short-circuiting Operators .....................................................................................................................25
Section 3.6: ? : Ternary Operator .............................................................................................................................26
Section 3.7: ?. (Null Conditional Operator) ...............................................................................................................27
Section 3.8: "Exclusive or" Operator .........................................................................................................................27
Section 3.9: default Operator ....................................................................................................................................28
Section 3.10: Assignment operator '=' ......................................................................................................................28
Section 3.11: sizeof...................................................................................................................................................28
Section 3.12: ?? Null-Coalescing Operator ..............................................................................................................29
Section 3.13: Bit-Shifting Operators .........................................................................................................................29
Section 3.14: => Lambda operator ...........................................................................................................................29
Section 3.15: Class Member Operators: Null Conditional Member Access .............................................................31
Section 3.16: Class Member Operators: Null Conditional Indexing .........................................................................31
Section 3.17: Postfix and Prefix increment and decrement ......................................................................................31
Section 3.18: typeof ..................................................................................................................................................32
Section 3.19: Binary operators with assignment ......................................................................................................32
Section 3.20: nameof Operator .................................................................................................................................32
Section 3.21: Class Member Operators: Member Access........................................................................................33
Section 3.22: Class Member Operators: Function Invocation ..................................................................................33
Section 3.23: Class Member Operators: Aggregate Object Indexing .......................................................................33
Chapter 4: Conditional Statements ..............................................................................................34
Section 4.1: If-Else Statement ..................................................................................................................................34
Section 4.2: If statement conditions are standard boolean expressions and values ................................................34
Section 4.3: If-Else If-Else Statement .......................................................................................................................35
Chapter 5: Equality Operator........................................................................................................36
Section 5.1: Equality kinds in c# and equality operator ............................................................................................36
Chapter 6: Equals and GetHashCode ..........................................................................................37
Section 6.1: Writing a good GetHashCode override.................................................................................................37
Section 6.2: Default Equals behavior........................................................................................................................37
Section 6.3: Override Equals and GetHashCode on custom types ..........................................................................38
Section 6.4: Equals and GetHashCode in IEqualityComparator ..............................................................................39
Chapter 7: Null-Coalescing Operator ..........................................................................................41
Section 7.1: Basic usage ..........................................................................................................................................41
Section 7.2: Null fall-through and chaining ...............................................................................................................41
Section 7.3: Null coalescing operator with method calls ..........................................................................................42
Section 7.4: Use existing or create new ...................................................................................................................43
Section 7.5: Lazy properties initialization with null coalescing operator ...................................................................43
Chapter 8: Null-conditional Operators.........................................................................................44
Section 8.1: Null-Conditional Operator .....................................................................................................................44
Section 8.2: The Null-Conditional Index ...................................................................................................................44
Section 8.3: Avoiding NullReferenceExceptions ......................................................................................................45
Section 8.4: Null-conditional Operator can be used with Extension Method ............................................................45
Chapter 9: nameof Operator .........................................................................................................47
Section 9.1: Basic usage: Printing a variable name .................................................................................................47
Section 9.2: Raising PropertyChanged event ...........................................................................................................47
Section 9.3: Argument Checking and Guard Clauses ..............................................................................................48
Section 9.4: Strongly typed MVC action links ...........................................................................................................48
Section 9.5: Handling PropertyChanged events .......................................................................................................49
Section 9.6: Applied to a generic type parameter .....................................................................................................49
Section 9.7: Printing a parameter name ...................................................................................................................50
Section 9.8: Applied to qualified identifiers ...............................................................................................................50
Chapter 10: Verbatim Strings .......................................................................................................51
Section 10.1: Interpolated Verbatim Strings .............................................................................................................51
Section 10.2: Escaping Double Quotes ....................................................................................................................51
Section 10.3: Verbatim strings instruct the compiler to not use character escapes .................................................51
Section 10.4: Multiline Strings ..................................................................................................................................52
Chapter 11: Common String Operations .....................................................................................53
Section 11.1: Formatting a string ..............................................................................................................................53
Section 11.2: Correctly reversing a string .................................................................................................................53
Section 11.3: Padding a string to a fixed length .......................................................................................................54
Section 11.4: Getting x characters from the right side of a string .............................................................................55
Section 11.5: Checking for empty String using String.IsNullOrEmpty() and String.IsNullOrWhiteSpace()
56
Section 11.6: Trimming Unwanted Characters O the Start and/or End of Strings .................................................57
Section 11.7: Convert Decimal Number to Binary,Octal and Hexadecimal Format .................................................57
Section 11.8: Construct a string from Array ..............................................................................................................57
Section 11.9: Formatting using ToString ..................................................................................................................58
Section 11.10: Splitting a String by another string ....................................................................................................59
Section 11.11: Splitting a String by specific character..............................................................................................59
Section 11.12: Getting Substrings of a given string ..................................................................................................59
Section 11.13: Determine whether a string begins with a given sequence ..............................................................59
Section 11.14: Getting a char at specific index and enumerating the string ............................................................59
Section 11.15: Joining an array of strings into a new one ........................................................................................60
Section 11.16: Replacing a string within a string ......................................................................................................60
Section 11.17: Changing the case of characters within a String ..............................................................................60
Section 11.18: Concatenate an array of strings into a single string .........................................................................61
Section 11.19: String Concatenation ........................................................................................................................61
Chapter 12: String.Format ............................................................................................................62
Section 12.1: Since C# 6.0 .......................................................................................................................................62
Section 12.2: Places where String.Format is 'embedded' in the framework ............................................................62
Section 12.3: Create a custom format provider ........................................................................................................62
Section 12.4: Date Formatting ..................................................................................................................................63
Section 12.5: Currency Formatting ...........................................................................................................................64
Section 12.6: Using custom number format .............................................................................................................65
Section 12.7: Align left/ right, pad with spaces .........................................................................................................65
Section 12.8: Numeric formats .................................................................................................................................66
Section 12.9: ToString() ............................................................................................................................................66
Section 12.10: Escaping curly brackets inside a String.Format() expression ..........................................................67
Section 12.11: Relationship with ToString() .............................................................................................................67
Chapter 13: String Concatenate ...................................................................................................68
Section 13.1: + Operator...........................................................................................................................................68
Section 13.2: Concatenate strings using System.Text.StringBuilder .......................................................................68
Section 13.3: Concat string array elements using String.Join ..................................................................................68
Section 13.4: Concatenation of two strings using $ ..................................................................................................69
Chapter 14: String Manipulation ..................................................................................................70
Section 14.1: Replacing a string within a string ........................................................................................................70
Section 14.2: Finding a string within a string ............................................................................................................70
Section 14.3: Removing (Trimming) white-space from a string ................................................................................70
Section 14.4: Splitting a string using a delimiter .......................................................................................................71
Section 14.5: Concatenate an array of strings into a single string ...........................................................................71
Section 14.6: String Concatenation ..........................................................................................................................71
Section 14.7: Changing the case of characters within a String ................................................................................71
Chapter 15: String Interpolation...................................................................................................73
Section 15.1: Format dates in strings .......................................................................................................................73
Section 15.2: Padding the output..............................................................................................................................73
Section 15.3: Expressions ........................................................................................................................................74
Section 15.4: Formatting numbers in strings ............................................................................................................74
Section 15.5: Simple Usage .....................................................................................................................................75
Chapter 16: String Escape Sequences ........................................................................................76
Section 16.1: Escaping special symbols in string literals .........................................................................................76
Section 16.2: Unicode character escape sequences ...............................................................................................76
Section 16.3: Escaping special symbols in character literals ...................................................................................76
Section 16.4: Using escape sequences in identifiers ...............................................................................................76
Section 16.5: Unrecognized escape sequences produce compile-time errors ........................................................77
Chapter 17: StringBuilder .............................................................................................................78
Section 17.1: What a StringBuilder is and when to use one ....................................................................................78
Section 17.2: Use StringBuilder to create string from a large number of records ....................................................79
Chapter 18: Regex Parsing ...........................................................................................................80
Section 18.1: Single match .......................................................................................................................................80
Section 18.2: Multiple matches .................................................................................................................................80
Chapter 19: DateTime Methods ....................................................................................................81
Section 19.1: DateTime Formatting ..........................................................................................................................81
Section 19.2: DateTime.AddDays(Double) ...............................................................................................................82
Section 19.3: DateTime.AddHours(Double) .............................................................................................................82
Section 19.4: DateTime.Parse(String) ......................................................................................................................82
Section 19.5: DateTime.TryParse(String, DateTime) ...............................................................................................82
Section 19.6: DateTime.AddMilliseconds(Double) ...................................................................................................83
Section 19.7: DateTime.Compare(DateTime t1, DateTime t2 ) ...............................................................................83
Section 19.8: DateTime.DaysInMonth(Int32, Int32) ................................................................................................83
Section 19.9: DateTime.AddYears(Int32) .................................................................................................................84
Section 19.10: Pure functions warning when dealing with DateTime.......................................................................84
Section 19.11: DateTime.TryParseExact(String, String, IFormatProvider, DateTimeStyles, DateTime)
84
Section 19.12: DateTime.Add(TimeSpan) ................................................................................................................86
Section 19.13: Parse and TryParse with culture info ................................................................................................86
Section 19.14: DateTime as initializer in for-loop .....................................................................................................87
Section 19.15: DateTime.ParseExact(String, String, IFormatProvider) .................................................................87
Section 19.16: DateTime ToString, ToShortDateString, ToLongDateString and ToString formatted ......................88
Section 19.17: Current Date .....................................................................................................................................88
Chapter 20: Arrays ........................................................................................................................89
Section 20.1: Declaring an array ..............................................................................................................................89
Section 20.2: Initializing an array filled with a repeated non-default value ...............................................................89
Section 20.3: Copying arrays ....................................................................................................................................90
Section 20.4: Comparing arrays for equality ............................................................................................................90
Section 20.5: Multi-dimensional arrays .....................................................................................................................91
Section 20.6: Getting and setting array values .........................................................................................................91
Section 20.7: Iterate over an array ...........................................................................................................................91
Section 20.8: Creating an array of sequential numbers ...........................................................................................92
Section 20.9: Jagged arrays .....................................................................................................................................92
Section 20.10: Array covariance ...............................................................................................................................94
Section 20.11: Arrays as IEnumerable<> instances .................................................................................................94
Section 20.12: Checking if one array contains another array ...................................................................................94
Chapter 21: O(n) Algorithm for circular rotation of an array .....................................................96
Section 21.1: Example of a generic method that rotates an array by a given shift ..................................................96
Chapter 22: Enum..........................................................................................................................98
Section 22.1: Enum basics .......................................................................................................................................98
Section 22.2: Enum as flags .....................................................................................................................................99
Section 22.3: Using << notation for flags ............................................................................................................... 101
Section 22.4: Test flags-style enum values with bitwise logic ............................................................................... 101
Section 22.5: Add and remove values from flagged enum .................................................................................... 102
Section 22.6: Enum to string and back .................................................................................................................. 102
Section 22.7: Enums can have unexpected values ............................................................................................... 103
Section 22.8: Default value for enum == ZERO .................................................................................................... 103
Section 22.9: Adding additional description information to an enum value ........................................................... 104
Section 22.10: Get all the members values of an enum ........................................................................................ 105
Section 22.11: Bitwise Manipulation using enums ................................................................................................ 105
Chapter 23: Tuples ...................................................................................................................... 106
Section 23.1: Accessing tuple elements ................................................................................................................ 106
Section 23.2: Creating tuples ................................................................................................................................. 106
Section 23.3: Comparing and sorting Tuples ........................................................................................................ 106
Section 23.4: Return multiple values from a method ............................................................................................. 107
Chapter 24: Guid ......................................................................................................................... 108
Section 24.1: Getting the string representation of a Guid...................................................................................... 108
Section 24.2: Creating a Guid ................................................................................................................................ 108
Section 24.3: Declaring a nullable GUID ............................................................................................................... 108
Chapter 25: BigInteger ................................................................................................................ 110
Section 25.1: Calculate the First 1,000-Digit Fibonacci Number ........................................................................... 110
Chapter 26: Collection Initializers .............................................................................................. 111
Section 26.1: Collection initializers ........................................................................................................................ 111
Section 26.2: C# 6 Index Initializers ...................................................................................................................... 111
Section 26.3: Collection initializers in custom classes ........................................................................................... 112
Section 26.4: Using collection initializer inside object initializer ............................................................................ 113
Section 26.5: Collection Initializers with Parameter Arrays ................................................................................... 114
Chapter 27: An overview of C# collections ............................................................................... 115
Section 27.1: HashSet<T> ..................................................................................................................................... 115
Section 27.2: Dictionary<TKey, TValue> ............................................................................................................... 115
Section 27.3: SortedSet<T> .................................................................................................................................. 116
Section 27.4: T[ ] (Array of T) ................................................................................................................................ 116
Section 27.5: List<T> ............................................................................................................................................. 117
Section 27.6: Stack<T> ......................................................................................................................................... 117
Section 27.7: LinkedList<T> .................................................................................................................................. 117
Section 27.8: Queue .............................................................................................................................................. 118
Chapter 28: Looping ................................................................................................................... 119
Section 28.1: For Loop .......................................................................................................................................... 119
Section 28.2: Do - While Loop ............................................................................................................................... 120
Section 28.3: Foreach Loop ................................................................................................................................... 120
Section 28.4: Looping styles .................................................................................................................................. 121
Section 28.5: Nested loops .................................................................................................................................... 122
Section 28.6: continue ........................................................................................................................................... 122
Section 28.7: While loop ........................................................................................................................................ 123
Section 28.8: break ................................................................................................................................................ 123
Chapter 29: Iterators ................................................................................................................... 125
Section 29.1: Creating Iterators Using Yield .......................................................................................................... 125
Section 29.2: Simple Numeric Iterator Example .................................................................................................... 126
Chapter 30: IEnumerable ............................................................................................................ 127
Section 30.1: IEnumerable with custom Enumerator ............................................................................................ 127
Section 30.2: IEnumerable<int> ............................................................................................................................ 128
Chapter 31: Value type vs Reference type ................................................................................ 129
Section 31.1: Passing by reference using ref keyword.......................................................................................... 129
Section 31.2: Changing values elsewhere ............................................................................................................ 130
Section 31.3: ref vs out parameters ....................................................................................................................... 131
Section 31.4: Assignment ...................................................................................................................................... 132
Section 31.5: Di erence with method parameters ref and out .............................................................................. 132
Section 31.6: Passing by reference ....................................................................................................................... 133
Chapter 32: Built-in Types .......................................................................................................... 134
Section 32.1: Conversion of boxed value types .................................................................................................... 134
Section 32.2: Comparisons with boxed value types .............................................................................................. 134
Section 32.3: Immutable reference type - string .................................................................................................... 134
Section 32.4: Value type - char .............................................................................................................................. 135
Section 32.5: Value type - short, int, long (signed 16 bit, 32 bit, 64 bit integers) .................................................. 135
Section 32.6: Value type - ushort, uint, ulong (unsigned 16 bit, 32 bit, 64 bit integers) ........................................ 135
Section 32.7: Value type - bool .............................................................................................................................. 136
Chapter 33: Aliases of built-in types ......................................................................................... 137
Section 33.1: Built-In Types Table ......................................................................................................................... 137
Chapter 34: Anonymous types ................................................................................................... 138
Section 34.1: Anonymous vs dynamic ................................................................................................................... 138
Section 34.2: Creating an anonymous type ........................................................................................................... 138
Section 34.3: Anonymous type equality ................................................................................................................ 138
Section 34.4: Generic methods with anonymous types......................................................................................... 139
Section 34.5: Instantiating generic types with anonymous types .......................................................................... 139
Section 34.6: Implicitly typed arrays ...................................................................................................................... 139
Chapter 35: Dynamic type .......................................................................................................... 141
Section 35.1: Creating a dynamic object with properties....................................................................................... 141
Section 35.2: Creating a dynamic variable ............................................................................................................ 141
Section 35.3: Returning dynamic ........................................................................................................................... 141
Section 35.4: Handling Specific Types Unknown at Compile Time ....................................................................... 141
Chapter 36: Type Conversion ..................................................................................................... 143
Section 36.1: Explicit Type Conversion ................................................................................................................. 143
Section 36.2: MSDN implicit operator example ..................................................................................................... 143
Chapter 37: Casting .................................................................................................................... 145
Section 37.1: Checking compatibility without casting ............................................................................................ 145
Section 37.2: Cast an object to a base type .......................................................................................................... 145
Section 37.3: Conversion Operators...................................................................................................................... 145
Section 37.4: LINQ Casting operations ................................................................................................................. 147
Section 37.5: Explicit Casting ................................................................................................................................ 147
Section 37.6: Safe Explicit Casting (`as` operator) ................................................................................................ 147
Section 37.7: Implicit Casting ................................................................................................................................ 148
Section 37.8: Explicit Numeric Conversions .......................................................................................................... 148
Chapter 38: Nullable types ......................................................................................................... 149
Section 38.1: Initialising a nullable......................................................................................................................... 149
Section 38.2: Check if a Nullable has a value ....................................................................................................... 149
Section 38.3: Get the value of a nullable type ....................................................................................................... 149
Section 38.4: Getting a default value from a nullable ............................................................................................ 150
Section 38.5: Default value of nullable types is null .............................................................................................. 150
Section 38.6: E ective usage of underlying Nullable<T> argument ...................................................................... 151
Section 38.7: Check if a generic type parameter is a nullable type ....................................................................... 152
Chapter 39: Constructors and Finalizers .................................................................................. 153
Section 39.1: Static constructor ............................................................................................................................. 153
Section 39.2: Singleton constructor pattern ........................................................................................................... 154
Section 39.3: Default Constructor .......................................................................................................................... 154
Section 39.4: Forcing a static constructor to be called .......................................................................................... 155
Section 39.5: Calling a constructor from another constructor ............................................................................... 156
Section 39.6: Calling the base class constructor ................................................................................................... 156
Section 39.7: Finalizers on derived classes .......................................................................................................... 157
Section 39.8: Exceptions in static constructors ..................................................................................................... 157
Section 39.9: Constructor and Property Initialization ............................................................................................. 158
Section 39.10: Generic Static Constructors ........................................................................................................... 160
Section 39.11: Calling virtual methods in constructor ............................................................................................ 160
Chapter 40: Access Modifiers .................................................................................................... 162
Section 40.1: Access Modifiers Diagrams ............................................................................................................. 162
Section 40.2: public................................................................................................................................................ 163
Section 40.3: private .............................................................................................................................................. 163
Section 40.4: protected internal ............................................................................................................................. 164
Section 40.5: internal ............................................................................................................................................. 165
Section 40.6: protected .......................................................................................................................................... 166
Chapter 41: Interfaces ................................................................................................................. 167
Section 41.1: Implementing an interface ............................................................................................................... 167
Section 41.2: Explicit interface implementation ..................................................................................................... 167
Section 41.3: Interface Basics ............................................................................................................................... 169
Section 41.4: IComparable<T> as an Example of Implementing an Interface ...................................................... 171
Section 41.5: Implementing multiple interfaces ..................................................................................................... 172
Section 41.6: Why we use interfaces..................................................................................................................... 172
Section 41.7: "Hiding" members with Explicit Implementation .............................................................................. 173
Chapter 42: Static Classes ......................................................................................................... 175
Section 42.1: Static Classes .................................................................................................................................. 175
Section 42.2: Static class lifetime .......................................................................................................................... 175
Section 42.3: Static keyword ................................................................................................................................. 176
Chapter 43: Singleton Implementation ...................................................................................... 177
Section 43.1: Statically Initialized Singleton .......................................................................................................... 177
Section 43.2: Lazy, thread-safe Singleton (using Lazy<T>) .................................................................................. 177
Section 43.3: Lazy, thread-safe Singleton (using Double Checked Locking) ....................................................... 177
Section 43.4: Lazy, thread safe singleton (for .NET 3.5 or older, alternate implementation) ................................ 178
Chapter 44: Dependency Injection ............................................................................................. 180
Section 44.1: Dependency Injection C# and ASP.NET with Unity ........................................................................ 180
Section 44.2: Dependency injection using MEF .................................................................................................... 182
Chapter 45: Partial class and methods ..................................................................................... 185
Section 45.1: Partial classes .................................................................................................................................. 185
Section 45.2: Partial classes inheriting from a base class..................................................................................... 185
Section 45.3: Partial methods ................................................................................................................................ 186
Chapter 46: Object initializers .................................................................................................... 187
Section 46.1: Simple usage ................................................................................................................................... 187
Section 46.2: Usage with non-default constructors ............................................................................................... 187
Section 46.3: Usage with anonymous types .......................................................................................................... 187
Chapter 47: Methods ................................................................................................................... 189
Section 47.1: Calling a Method .............................................................................................................................. 189
Section 47.2: Anonymous method ......................................................................................................................... 189
Section 47.3: Declaring a Method .......................................................................................................................... 190
Section 47.4: Parameters and Arguments ............................................................................................................. 190
Section 47.5: Return Types ................................................................................................................................... 190
Section 47.6: Default Parameters .......................................................................................................................... 191
Section 47.7: Method overloading ......................................................................................................................... 192
Section 47.8: Access rights ................................................................................................................................... 193
Chapter 48: Extension Methods ................................................................................................. 194
Section 48.1: Extension methods - overview......................................................................................................... 194
Section 48.2: Null checking ................................................................................................................................... 196
Section 48.3: Explicitly using an extension method............................................................................................... 197
Section 48.4: Generic Extension Methods ............................................................................................................ 197
Section 48.5: Extension methods can only see public (or internal) members of the extended class ................... 199
Section 48.6: Extension methods for chaining ...................................................................................................... 199
Section 48.7: Extension methods with Enumeration ............................................................................................. 200
Section 48.8: Extension methods dispatch based on static type .......................................................................... 201
Section 48.9: Extension methods on Interfaces .................................................................................................... 202
Section 48.10: Extension methods in combination with interfaces ........................................................................ 203
Section 48.11: Extension methods aren't supported by dynamic code ................................................................. 203
Section 48.12: Extensions and interfaces together enable DRY code and mixin-like functionality ...................... 204
Section 48.13: IList<T> Extension Method Example: Comparing 2 Lists.............................................................. 205
Section 48.14: Extension methods as strongly typed wrappers ............................................................................ 206
Section 48.15: Using Extension methods to create beautiful mapper classes ...................................................... 206
Section 48.16: Using Extension methods to build new collection types (e.g. DictList) ......................................... 207
Section 48.17: Extension methods for handling special cases ............................................................................. 208
Section 48.18: Using Extension methods with Static methods and Callbacks ...................................................... 209
Chapter 49: Named Arguments .................................................................................................. 211
Section 49.1: Argument order is not necessary..................................................................................................... 211
Section 49.2: Named arguments and optional parameters ................................................................................... 211
Section 49.3: Named Arguments can make your code more clear ....................................................................... 211
Chapter 50: Named and Optional Arguments ........................................................................... 213
Section 50.1: Optional Arguments ......................................................................................................................... 213
Section 50.2: Named Arguments ........................................................................................................................... 214
Chapter 51: Data Annotation ...................................................................................................... 217
Section 51.1: Data Annotation Basics ................................................................................................................... 217
Section 51.2: Creating a custom validation attribute ............................................................................................. 217
Section 51.3: Manually Execute Validation Attributes ........................................................................................... 218
Section 51.4: Validation Attributes ......................................................................................................................... 218
Section 51.5: EditableAttribute (data modeling attribute) ...................................................................................... 220
Chapter 52: Keywords ................................................................................................................ 222
Section 52.1: as ..................................................................................................................................................... 222
Section 52.2: goto .................................................................................................................................................. 223
Section 52.3: volatile .............................................................................................................................................. 224
Section 52.4: checked, unchecked ........................................................................................................................ 225
Section 52.5: virtual, override, new........................................................................................................................ 226
Section 52.6: stackalloc ......................................................................................................................................... 229
Section 52.7: break ................................................................................................................................................ 230
Section 52.8: const ................................................................................................................................................ 232
Section 52.9: async, await ..................................................................................................................................... 233
Section 52.10: for ................................................................................................................................................... 234
Section 52.11: abstract .......................................................................................................................................... 235
Section 52.12: fixed ............................................................................................................................................... 236
Section 52.13: default ............................................................................................................................................ 237
Section 52.14: sealed ............................................................................................................................................ 238
Section 52.15: is .................................................................................................................................................... 238
Section 52.16: this ................................................................................................................................................. 239
Section 52.17: readonly ......................................................................................................................................... 240
Section 52.18: typeof ............................................................................................................................................. 241
Section 52.19: foreach ........................................................................................................................................... 241
Section 52.20: dynamic ......................................................................................................................................... 242
Section 52.21: try, catch, finally, throw .................................................................................................................. 243
Section 52.22: void ................................................................................................................................................ 244
Section 52.23: namespace .................................................................................................................................... 244
Section 52.24: ref, out ............................................................................................................................................ 245
Section 52.25: base ............................................................................................................................................... 246
Section 52.26: float, double, decimal ..................................................................................................................... 248
Section 52.27: operator ......................................................................................................................................... 249
Section 52.28: char ................................................................................................................................................ 250
Section 52.29: params ........................................................................................................................................... 250
Section 52.30: while ............................................................................................................................................... 251
Section 52.31: null ................................................................................................................................................. 253
Section 52.32: continue ......................................................................................................................................... 254
Section 52.33: string .............................................................................................................................................. 254
Section 52.34: return ............................................................................................................................................. 255
Section 52.35: unsafe ............................................................................................................................................ 255
Section 52.36: switch ............................................................................................................................................. 257
Section 52.37: var .................................................................................................................................................. 258
Section 52.38: when .............................................................................................................................................. 259
Section 52.39: lock................................................................................................................................................. 260
Section 52.40: uint ................................................................................................................................................. 261
Section 52.41: if, if else, if . else if .......................................................................................................................... 261
Section 52.42: static .............................................................................................................................................. 262
Section 52.43: internal ........................................................................................................................................... 264
Section 52.44: using .............................................................................................................................................. 265
Section 52.45: where ............................................................................................................................................. 265
Section 52.46: int ................................................................................................................................................... 267
Section 52.47: ulong .............................................................................................................................................. 268
Section 52.48: true, false ....................................................................................................................................... 268
Section 52.49: struct .............................................................................................................................................. 268
Section 52.50: extern ............................................................................................................................................. 269
Section 52.51: bool ................................................................................................................................................ 270
Section 52.52: interface ......................................................................................................................................... 270
Section 52.53: delegate ......................................................................................................................................... 271
Section 52.54: unchecked ..................................................................................................................................... 271
Section 52.55: ushort ............................................................................................................................................. 272
Section 52.56: sizeof ............................................................................................................................................. 272
Section 52.57: in .................................................................................................................................................... 272
Section 52.58: implicit ............................................................................................................................................ 273
Section 52.59: do ................................................................................................................................................... 273
Section 52.60: long ................................................................................................................................................ 274
Section 52.61: enum .............................................................................................................................................. 274
Section 52.62: partial ............................................................................................................................................. 275
Section 52.63: event .............................................................................................................................................. 276
Section 52.64: sbyte .............................................................................................................................................. 277
Chapter 53: Object Oriented Programming In C# ..................................................................... 278
Section 53.1: Classes: ........................................................................................................................................... 278
Chapter 54: Recursion ................................................................................................................ 279
Section 54.1: Recursion in plain English ............................................................................................................... 279
Section 54.2: Fibonacci Sequence ........................................................................................................................ 279
Section 54.3: PowerOf calculation ......................................................................................................................... 280
Section 54.4: Recursively describe an object structure ......................................................................................... 280
Section 54.5: Using Recursion to Get Directory Tree ............................................................................................ 281
Section 54.6: Factorial calculation ......................................................................................................................... 284
Chapter 55: Naming Conventions .............................................................................................. 285
Section 55.1: Capitalization conventions ............................................................................................................... 285
Section 55.2: Enums .............................................................................................................................................. 286
Section 55.3: Interfaces ......................................................................................................................................... 286
Section 55.4: Exceptions ....................................................................................................................................... 286
Section 55.5: Private fields .................................................................................................................................... 287
Section 55.6: Namespaces .................................................................................................................................... 287
Chapter 56: XML Documentation Comments............................................................................ 288
Section 56.1: Simple method annotation ............................................................................................................... 288
Section 56.2: Generating XML from documentation comments ............................................................................ 288
Section 56.3: Method documentation comment with param and returns elements .............................................. 290
Section 56.4: Interface and class documentation comments ................................................................................ 290
Section 56.5: Referencing another class in documentation .................................................................................. 291
Chapter 57: Comments and regions .......................................................................................... 292
Section 57.1: Comments ....................................................................................................................................... 292
Section 57.2: Regions ............................................................................................................................................ 292
Section 57.3: Documentation comments ............................................................................................................... 293
Chapter 58: Inheritance............................................................................................................... 295
Section 58.1: Inheritance. Constructors' calls sequence ....................................................................................... 295
Section 58.2: Inheriting from a base class ............................................................................................................. 297
Section 58.3: Inheriting from a class and implementing an interface .................................................................... 298
Section 58.4: Inheriting from a class and implementing multiple interfaces .......................................................... 298
Section 58.5: Constructors In A Subclass ............................................................................................................. 299
Section 58.6: Inheritance Anti-patterns ................................................................................................................. 299
Section 58.7: Extending an abstract base class .................................................................................................... 300
Section 58.8: Testing and navigating inheritance .................................................................................................. 301
Section 58.9: Inheriting methods ........................................................................................................................... 301
Section 58.10: Base class with recursive type specification ................................................................................. 302
Chapter 59: Generics .................................................................................................................. 305
Section 59.1: Implicit type inference (methods) ..................................................................................................... 305
Section 59.2: Type inference (classes) ................................................................................................................. 306
Section 59.3: Using generic method with an interface as a constraint type .......................................................... 306
Section 59.4: Type constraints (new-keyword) ...................................................................................................... 307
Section 59.5: Type constraints (classes and interfaces) ....................................................................................... 308
Section 59.6: Checking equality of generic values ................................................................................................ 309
Section 59.7: Reflecting on type parameters ......................................................................................................... 310
Section 59.8: Covariance ....................................................................................................................................... 310
Section 59.9: Contravariance ................................................................................................................................ 311
Section 59.10: Invariance ...................................................................................................................................... 312
Section 59.11: Variant interfaces ........................................................................................................................... 312
Section 59.12: Variant delegates ........................................................................................................................... 313
Section 59.13: Variant types as parameters and return values ............................................................................. 314
Section 59.14: Type Parameters (Interfaces) ........................................................................................................ 314
Section 59.15: Type constraints (class and struct) ................................................................................................ 315
Section 59.16: Explicit type parameters ................................................................................................................ 315
Section 59.17: Type Parameters (Classes) ........................................................................................................... 315
Section 59.18: Type Parameters (Methods) .......................................................................................................... 316
Section 59.19: Generic type casting ...................................................................................................................... 316
Section 59.20: Configuration reader with generic type casting ............................................................................. 317
Chapter 60: Using Statement ..................................................................................................... 319
Section 60.1: Using Statement Basics................................................................................................................... 319
Section 60.2: Gotcha: returning the resource which you are disposing ................................................................ 320
Section 60.3: Multiple using statements with one block ........................................................................................ 321
Section 60.4: Gotcha: Exception in Dispose method masking other errors in Using blocks ................................. 322
Section 60.5: Using statements are null-safe ........................................................................................................ 322
Section 60.6: Using Dispose Syntax to define custom scope ............................................................................... 322
Section 60.7: Using Statements and Database Connections ................................................................................ 323
Section 60.8: Executing code in constraint context ............................................................................................... 325
Chapter 61: Using Directive ........................................................................................................ 326
Section 61.1: Associate an Alias to Resolve Conflicts .......................................................................................... 326
Section 61.2: Using alias directives ....................................................................................................................... 326
Section 61.3: Access Static Members of a Class .................................................................................................. 326
Section 61.4: Basic Usage ..................................................................................................................................... 327
Section 61.5: Reference a Namespace ................................................................................................................. 327
Section 61.6: Associate an Alias with a Namespace ............................................................................................. 327
Chapter 62: IDisposable interface .............................................................................................. 329
Section 62.1: In a class that contains only managed resources ........................................................................... 329
Section 62.2: In a class with managed and unmanaged resources ...................................................................... 329
Section 62.3: IDisposable, Dispose ....................................................................................................................... 330
Section 62.4: using keyword .................................................................................................................................. 330
Section 62.5: In an inherited class with managed resources ................................................................................ 331
Chapter 63: Reflection ................................................................................................................ 332
Section 63.1: Get the members of a type .............................................................................................................. 332
Section 63.2: Get a method and invoke it .............................................................................................................. 332
Section 63.3: Creating an instance of a Type ........................................................................................................ 333
Section 63.4: Get a Strongly-Typed Delegate to a Method or Property via Reflection ......................................... 336
Section 63.5: Get a generic method and invoke it ................................................................................................. 337
Section 63.6: Get a System.Type .......................................................................................................................... 338
Section 63.7: Getting and setting properties ......................................................................................................... 338
Section 63.8: Create an instance of a Generic Type and invoke it's method ........................................................ 338
Section 63.9: Custom Attributes ............................................................................................................................ 339
Section 63.10: Instantiating classes that implement an interface (e.g. plugin activation) ..................................... 340
Section 63.11: Get a Type by name with namespace ........................................................................................... 340
Section 63.12: Determining generic arguments of instances of generic types ..................................................... 341
Section 63.13: Looping through all the properties of a class ................................................................................. 342
Chapter 64: IQueryable interface ............................................................................................... 343
Section 64.1: Translating a LINQ query to a SQL query ....................................................................................... 343
Chapter 65: Linq to Objects........................................................................................................ 344
Section 65.1: Using LINQ to Objects in C# ........................................................................................................... 344
Chapter 66: LINQ Queries ........................................................................................................... 348
Section 66.1: Chaining methods ............................................................................................................................ 348
Section 66.2: First, FirstOrDefault, Last, LastOrDefault, Single, and SingleOrDefault ......................................... 349
Section 66.3: Except .............................................................................................................................................. 352
Section 66.4: SelectMany ...................................................................................................................................... 354
Section 66.5: Any ................................................................................................................................................... 355
Section 66.6: JOINS .............................................................................................................................................. 355
Section 66.7: Skip and Take .................................................................................................................................. 358
Section 66.8: Defining a variable inside a Linq query (let keyword) ...................................................................... 358
Section 66.9: Zip .................................................................................................................................................... 359
Section 66.10: Range and Repeat......................................................................................................................... 359
Section 66.11: Basics ............................................................................................................................................ 360
Section 66.12: All ................................................................................................................................................... 360
Section 66.13: Aggregate ...................................................................................................................................... 361
Section 66.14: Distinct ........................................................................................................................................... 362
Section 66.15: SelectMany: Flattening a sequence of sequences ........................................................................ 362
Section 66.16: GroupBy ......................................................................................................................................... 364
Section 66.17: Query collection by type / cast elements to type ........................................................................... 365
Section 66.18: Enumerating the Enumerable ........................................................................................................ 366
Section 66.19: Using Range with various Linq methods ....................................................................................... 367
Section 66.20: Where ............................................................................................................................................ 368
Section 66.21: Using SelectMany instead of nested loops ................................................................................... 368
Section 66.22: Contains ......................................................................................................................................... 368
Section 66.23: Joining multiple sequences ........................................................................................................... 370
Section 66.24: Joining on multiple keys ................................................................................................................ 372
Section 66.25: ToLookup ....................................................................................................................................... 372
Section 66.26: SkipWhile ....................................................................................................................................... 372
Section 66.27: Query Ordering - OrderBy() ThenBy() OrderByDescending() ThenByDescending() .................... 373
Section 66.28: Sum................................................................................................................................................ 374
Section 66.29: GroupBy one or multiple fields ...................................................................................................... 374
Section 66.30: OrderBy ......................................................................................................................................... 375
Section 66.31: Any and First(OrDefault) - best practice ........................................................................................ 376
Section 66.32: GroupBy Sum and Count .............................................................................................................. 376
Section 66.33: SequenceEqual ............................................................................................................................. 377
Section 66.34: ElementAt and ElementAtOrDefault .............................................................................................. 377
Section 66.35: DefaultIfEmpty ............................................................................................................................... 378
Section 66.36: ToDictionary ................................................................................................................................... 379
Section 66.37: Concat ........................................................................................................................................... 380
Section 66.38: Build your own Linq operators for IEnumerable<T> ...................................................................... 380
Section 66.39: Select - Transforming elements ..................................................................................................... 381
Section 66.40: OrderByDescending ...................................................................................................................... 382
Section 66.41: Union ............................................................................................................................................. 382
Section 66.42: GroupJoin with outer range variable.............................................................................................. 383
Section 66.43: Linq Quantifiers .............................................................................................................................. 383
Section 66.44: TakeWhile ...................................................................................................................................... 383
Section 66.45: Reverse ......................................................................................................................................... 384
Section 66.46: Count and LongCount.................................................................................................................... 385
Section 66.47: Incrementally building a query ....................................................................................................... 385
Section 66.48: Select with Func<TSource, int, TResult> selector - Use to get ranking of elements .................... 387
Chapter 67: LINQ to XML ............................................................................................................ 389
Section 67.1: Read XML using LINQ to XML ........................................................................................................ 389
Chapter 68: Parallel LINQ (PLINQ) ............................................................................................. 391
Section 68.1: Simple example ............................................................................................................................... 391
Section 68.2: WithDegreeOfParallelism ................................................................................................................ 391
Section 68.3: AsOrdered ....................................................................................................................................... 391
Section 68.4: AsUnordered .................................................................................................................................... 391
Chapter 69: XmlDocument and the System.Xml namespace .................................................. 392
Section 69.1: XmlDocument vs XDocument (Example and comparison) ............................................................. 392
Section 69.2: Reading from XML document .......................................................................................................... 394
Section 69.3: Basic XML document interaction ..................................................................................................... 395
Chapter 70: XDocument and the System.Xml.Linq namespace .............................................. 396
Section 70.1: Generate an XML document ........................................................................................................... 396
Section 70.2: Generate an XML document using fluent syntax ............................................................................ 396
Section 70.3: Modify XML File ............................................................................................................................... 397
Chapter 71: C# 7.0 Features ....................................................................................................... 399
Section 71.1: Language support for Tuples ........................................................................................................... 399
Section 71.2: Local functions ................................................................................................................................. 403
Section 71.3: out var declaration ........................................................................................................................... 404
Section 71.4: Pattern Matching .............................................................................................................................. 405
Section 71.5: Digit separators ................................................................................................................................ 407
Section 71.6: Binary literals ................................................................................................................................... 407
Section 71.7: throw expressions ............................................................................................................................ 408
Section 71.8: Extended expression bodied members list ...................................................................................... 409
Section 71.9: ref return and ref local...................................................................................................................... 410
Section 71.10: ValueTask<T> ............................................................................................................................... 411
Chapter 72: C# 6.0 Features ....................................................................................................... 413
Section 72.1: Exception filters ............................................................................................................................... 413
Section 72.2: String interpolation ........................................................................................................................... 417
Section 72.3: Auto-property initializers .................................................................................................................. 423
Section 72.4: Null propagation ............................................................................................................................... 426
Section 72.5: Expression-bodied function members ............................................................................................. 429
Section 72.6: Operator nameof .............................................................................................................................. 431
Section 72.7: Using static type .............................................................................................................................. 433
Section 72.8: Index initializers ............................................................................................................................... 433
Section 72.9: Improved overload resolution .......................................................................................................... 435
Section 72.10: Await in catch and finally ............................................................................................................... 436
Section 72.11: Minor changes and bugfixes .......................................................................................................... 437
Section 72.12: Using an extension method for collection initialization .................................................................. 437
Section 72.13: Disable Warnings Enhancements ................................................................................................. 438
Chapter 73: C# 5.0 Features ....................................................................................................... 440
Section 73.1: Async & Await .................................................................................................................................. 440
Section 73.2: Caller Information Attributes ............................................................................................................ 441
Chapter 74: C# 4.0 Features ....................................................................................................... 442
Section 74.1: Optional parameters and named arguments ................................................................................... 442
Section 74.2: Variance ........................................................................................................................................... 443
Section 74.3: Dynamic member lookup ................................................................................................................. 443
Section 74.4: Optional ref keyword when using COM ........................................................................................... 444
Chapter 75: C# 3.0 Features ....................................................................................................... 445
Section 75.1: Implicitly typed variables (var) ......................................................................................................... 445
Section 75.2: Language Integrated Queries (LINQ) .............................................................................................. 445
Section 75.3: Lambda expresions ......................................................................................................................... 446
Section 75.4: Anonymous types ............................................................................................................................ 446
Chapter 76: Exception Handling ................................................................................................ 448
Section 76.1: Creating Custom Exceptions ........................................................................................................... 448
Section 76.2: Finally block ..................................................................................................................................... 450
Section 76.3: Best Practices .................................................................................................................................. 451
Section 76.4: Exception Anti-patterns ................................................................................................................... 453
Section 76.5: Basic Exception Handling ................................................................................................................ 455
Section 76.6: Handling specific exception types ................................................................................................... 455
Section 76.7: Aggregate exceptions / multiple exceptions from one method ........................................................ 456
Section 76.8: Throwing an exception..................................................................................................................... 457
Section 76.9: Unhandled and Thread Exception ................................................................................................... 457
Section 76.10: Implementing IErrorHandler for WCF Services ............................................................................. 458
Section 76.11: Using the exception object ............................................................................................................ 460
Section 76.12: Nesting of Exceptions & try catch blocks ...................................................................................... 462
Chapter 77: NullReferenceException ........................................................................................ 463
Section 77.1: NullReferenceException explained .................................................................................................. 463
Chapter 78: Handling FormatException when converting string to other types ................... 464
Section 78.1: Converting string to integer ............................................................................................................. 464
Chapter 79: Read & Understand Stacktraces ........................................................................... 466
Section 79.1: Stack trace for a simple NullReferenceException in Windows Forms ............................................ 466
Chapter 80: Diagnostics ............................................................................................................. 468
Section 80.1: Redirecting log output with TraceListeners ..................................................................................... 468
Section 80.2: Debug.WriteLine .............................................................................................................................. 468
Chapter 81: Overflow .................................................................................................................. 469
Section 81.1: Integer overflow ............................................................................................................................... 469
Section 81.2: Overflow during operation ............................................................................................................... 469
Section 81.3: Ordering matters .............................................................................................................................. 469
Chapter 82: Getting Started: Json with C#................................................................................ 470
Section 82.1: Simple Json Example ...................................................................................................................... 470
Section 82.2: First things First: Library to work with Json ..................................................................................... 470
Section 82.3: C# Implementation ........................................................................................................................... 470
Section 82.4: Serialization ..................................................................................................................................... 471
Section 82.5: Deserialization ................................................................................................................................. 471
Section 82.6: Serialization & De-Serialization Common Utilities function ............................................................. 471
Chapter 83: Using json.net ......................................................................................................... 473
Section 83.1: Using JsonConverter on simple values ........................................................................................... 473
Section 83.2: Collect all fields of JSON object ...................................................................................................... 475
Chapter 84: Lambda expressions .............................................................................................. 477
Section 84.1: Lambda Expressions as Shorthand for Delegate Initialization ........................................................ 477
Section 84.2: Lambda Expression as an Event Handler ....................................................................................... 477
Section 84.3: Lambda Expressions with Multiple Parameters or No Parameters ................................................. 478
Section 84.4: Lambdas can be emitted both as `Func` and `Expression`............................................................. 478
Section 84.5: Put Multiple Statements in a Statement Lambda ............................................................................ 478
Section 84.6: Lambdas for both `Func` and `Action` ............................................................................................. 479
Section 84.7: Using lambda syntax to create a closure......................................................................................... 479
Section 84.8: Passing a Lambda Expression as a Parameter to a Method .......................................................... 479
Section 84.9: Basic lambda expressions ............................................................................................................... 479
Section 84.10: Basic lambda expressions with LINQ ............................................................................................ 480
Section 84.11: Lambda syntax with statement block body .................................................................................... 480
Section 84.12: Lambda expressions with System.Linq.Expressions .................................................................... 480
Chapter 85: Generic Lambda Query Builder ............................................................................. 481
Section 85.1: QueryFilter class .............................................................................................................................. 481
Section 85.2: GetExpression Method .................................................................................................................... 481
Section 85.3: GetExpression Private overload ...................................................................................................... 482
Section 85.4: ConstantExpression Method ........................................................................................................... 483
Section 85.5: Usage .............................................................................................................................................. 484
Chapter 86: Properties ................................................................................................................ 485
Section 86.1: Auto-implemented properties .......................................................................................................... 485
Section 86.2: Default Values for Properties ........................................................................................................... 485
Section 86.3: Public Get ........................................................................................................................................ 486
Section 86.4: Public Set ......................................................................................................................................... 486
Section 86.5: Accessing Properties ....................................................................................................................... 486
Section 86.6: Read-only properties ....................................................................................................................... 488
Section 86.7: Various Properties in Context .......................................................................................................... 488
Chapter 87: Initializing Properties ............................................................................................. 490
Section 87.1: C# 6.0: Initialize an Auto-Implemented Property ............................................................................. 490
Section 87.2: Initializing Property with a Backing Field ......................................................................................... 490
Section 87.3: Property Initialization during object instantiation ............................................................................. 490
Section 87.4: Initializing Property in Constructor ................................................................................................... 490
Chapter 88: INotifyPropertyChanged interface ......................................................................... 491
Section 88.1: Implementing INotifyPropertyChanged in C# 6 ............................................................................... 491
Section 88.2: INotifyPropertyChanged With Generic Set Method ......................................................................... 492
Chapter 89: Events ...................................................................................................................... 494
Section 89.1: Declaring and Raising Events ......................................................................................................... 494
Section 89.2: Event Properties .............................................................................................................................. 495
Section 89.3: Creating cancelable event ............................................................................................................... 496
Section 89.4: Standard Event Declaration ............................................................................................................. 497
Section 89.5: Anonymous Event Handler Declaration........................................................................................... 498
Section 89.6: Non-Standard Event Declaration ..................................................................................................... 498
Section 89.7: Creating custom EventArgs containing additional data ................................................................... 499
Chapter 90: Expression Trees .................................................................................................... 501
Section 90.1: Create Expression Trees with a lambda expression ....................................................................... 501
Section 90.2: Creating Expression Trees by Using the API .................................................................................. 501
Section 90.3: Compiling Expression Trees ............................................................................................................ 501
Section 90.4: Parsing Expression Trees ............................................................................................................... 502
Section 90.5: Expression Tree Basic ..................................................................................................................... 502
Section 90.6: Examining the Structure of an Expression using Visitor .................................................................. 503
Section 90.7: Understanding the expressions API ................................................................................................ 503
Chapter 91: Overload Resolution............................................................................................... 505
Section 91.1: Basic Overloading Example ............................................................................................................ 505
Section 91.2: "params" is not expanded, unless necessary .................................................................................. 505
Section 91.3: Passing null as one of the arguments ............................................................................................. 506
Chapter 92: BindingList<T>........................................................................................................ 507
Section 92.1: Add item to list ................................................................................................................................. 507
Section 92.2: Avoiding N*2 iteration ...................................................................................................................... 507
Chapter 93: Preprocessor directives ......................................................................................... 508
Section 93.1: Conditional Expressions .................................................................................................................. 508
Section 93.2: Other Compiler Instructions ............................................................................................................. 508
Section 93.3: Defining and Undefining Symbols ................................................................................................... 509
Section 93.4: Region Blocks .................................................................................................................................. 510
Section 93.5: Disabling and Restoring Compiler Warnings ................................................................................... 510
Section 93.6: Generating Compiler Warnings and Errors ..................................................................................... 510
Section 93.7: Custom Preprocessors at project level ............................................................................................ 511
Section 93.8: Using the Conditional attribute ........................................................................................................ 511
Chapter 94: Structs ..................................................................................................................... 513
Section 94.1: Declaring a struct ............................................................................................................................. 513
Section 94.2: Struct usage ..................................................................................................................................... 514
Section 94.3: Structs are copied on assignment ................................................................................................... 515
Section 94.4: Struct implementing interface .......................................................................................................... 515
Chapter 95: Attributes ................................................................................................................. 516
Section 95.1: Creating a custom attribute ............................................................................................................. 516
Section 95.2: Reading an attribute ........................................................................................................................ 516
Section 95.3: Using an attribute ............................................................................................................................. 517
Section 95.4: DebuggerDisplay Attribute ............................................................................................................... 517
Section 95.5: Caller info attributes ......................................................................................................................... 518
Section 95.6: Obsolete Attribute ............................................................................................................................ 519
Section 95.7: Reading an attribute from interface ................................................................................................. 519
Chapter 96: Delegates ................................................................................................................. 521
Section 96.1: Declaring a delegate type ................................................................................................................ 521
Section 96.2: The Func<T, TResult>, Action<T> and Predicate<T> delegate types ............................................ 522
Section 96.3: Combine Delegates (Multicast Delegates) ...................................................................................... 523
Section 96.4: Safe invoke multicast delegate ........................................................................................................ 524
Section 96.5: Delegate Equality............................................................................................................................. 525
Section 96.6: Underlying references of named method delegates ........................................................................ 525
Section 96.7: Assigning a named method to a delegate ....................................................................................... 526
Section 96.8: Assigning to a delegate by lambda .................................................................................................. 527
Section 96.9: Encapsulating transformations in funcs ........................................................................................... 527
Section 96.10: Passing delegates as parameters ................................................................................................. 527
Section 96.11: Closure inside a delegate .............................................................................................................. 528
Chapter 97: File and Stream I/O ................................................................................................. 529
Section 97.1: Reading from a file using the System.IO.File class ......................................................................... 529
Section 97.2: Lazily reading a file line-by-line via an IEnumerable ....................................................................... 529
Section 97.3: Async write text to a file using StreamWriter ................................................................................... 529
Section 97.4: Copy File .......................................................................................................................................... 529
Section 97.5: Writing lines to a file using the System.IO.StreamWriter class ....................................................... 530
Section 97.6: Writing to a file using the System.IO.File class ............................................................................... 530
Section 97.7: Create File ....................................................................................................................................... 531
Section 97.8: Move File ......................................................................................................................................... 531
Section 97.9: Delete File ........................................................................................................................................ 532
Section 97.10: Files and Directories ...................................................................................................................... 532
Chapter 98: Networking .............................................................................................................. 533
Section 98.1: Basic TCP Communication Client ................................................................................................... 533
Section 98.2: Download a file from a web server .................................................................................................. 533
Section 98.3: Async TCP Client ............................................................................................................................. 534
Section 98.4: Basic UDP Client ............................................................................................................................. 535
Chapter 99: Performing HTTP requests .................................................................................... 536
Section 99.1: Creating and sending an HTTP POST request ............................................................................... 536
Section 99.2: Creating and sending an HTTP GET request ................................................................................. 536
Section 99.3: Error handling of specific HTTP response codes (such as 404 Not Found) ................................... 537
Section 99.4: Retrieve HTML for Web Page (Simple) ........................................................................................... 537
Section 99.5: Sending asynchronous HTTP POST request with JSON body ....................................................... 537
Chapter 100: Reading and writing .zip files .............................................................................. 539
Section 100.1: Writing to a zip file ......................................................................................................................... 539
Section 100.2: Writing Zip Files in-memory ........................................................................................................... 539
Section 100.3: Get files from a Zip file ................................................................................................................... 539
Section 100.4: The following example shows how to open a zip archive and extract all .txt files to a folder
540
Chapter 101: FileSystemWatcher ............................................................................................... 541
Section 101.1: IsFileReady .................................................................................................................................... 541
Section 101.2: Basic FileWatcher .......................................................................................................................... 541
Chapter 102: Access network shared folder with username and password .......................... 543
Section 102.1: Code to access network shared file ............................................................................................... 543
Chapter 103: Asynchronous Socket .......................................................................................... 545
Section 103.1: Asynchronous Socket (Client / Server) example ........................................................................... 545
Chapter 104: Action Filters ......................................................................................................... 552
Section 104.1: Custom Action Filters..................................................................................................................... 552
Chapter 105: Polymorphism ....................................................................................................... 553
Section 105.1: Types of Polymorphism ................................................................................................................. 553
Section 105.2: Another Polymorphism Example ................................................................................................... 554
Chapter 106: Immutability........................................................................................................... 557
Section 106.1: System.String class ....................................................................................................................... 557
Section 106.2: Strings and immutability................................................................................................................. 557
Chapter 107: Indexer ................................................................................................................... 558
Section 107.1: A simple indexer ............................................................................................................................ 558
Section 107.2: Overloading the indexer to create a SparseArray ......................................................................... 558
Section 107.3: Indexer with 2 arguments and interface ........................................................................................ 559
Chapter 108: Checked and Unchecked ..................................................................................... 560
Section 108.1: Checked and Unchecked .............................................................................................................. 560
Section 108.2: Checked and Unchecked as a scope ............................................................................................ 560
Chapter 109: Stream ................................................................................................................... 561
Section 109.1: Using Streams ............................................................................................................................... 561
Chapter 110: Timers .................................................................................................................... 563
Section 110.1: Multithreaded Timers ..................................................................................................................... 563
Section 110.2: Creating an Instance of a Timer .................................................................................................... 564
Section 110.3: Assigning the "Tick" event handler to a Timer ............................................................................... 565
Section 110.4: Example: Using a Timer to perform a simple countdown .............................................................. 565
Chapter 111: Stopwatches.......................................................................................................... 567
Section 111.1: IsHighResolution ............................................................................................................................ 567
Section 111.2: Creating an Instance of a Stopwatch............................................................................................. 567
Chapter 112: Threading .............................................................................................................. 569
Section 112.1: Avoiding Reading and Writing Data Simultaneously ..................................................................... 569
Section 112.2: Creating and Starting a Second Thread ........................................................................................ 570
Section 112.3: Parallel.ForEach Loop ................................................................................................................... 570
Section 112.4: Deadlocks (hold resource and wait) .............................................................................................. 571
Section 112.5: Simple Complete Threading Demo ............................................................................................... 573
Section 112.6: Creating One Thread Per Processor ............................................................................................. 574
Section 112.7: Simple Complete Threading Demo using Tasks ........................................................................... 574
Section 112.8: Deadlocks (two threads waiting on each other) ............................................................................ 575
Section 112.9: Explicit Task Parallism ................................................................................................................... 576
Section 112.10: Implicit Task Parallelism .............................................................................................................. 576
Section 112.11: Starting a thread with parameters ............................................................................................... 577
Chapter 113: Async/await, Backgroundworker, Task and Thread Examples ........................ 578
Section 113.1: ASP.NET Configure Await ............................................................................................................. 578
Section 113.2: Task "run and forget" extension .................................................................................................... 580
Section 113.3: Async/await .................................................................................................................................... 580
Section 113.4: BackgroundWorker ........................................................................................................................ 581
Section 113.5: Task ............................................................................................................................................... 582
Section 113.6: Thread ........................................................................................................................................... 583
Chapter 114: Async-Await .......................................................................................................... 584
Section 114.1: Await operator and async keyword ................................................................................................ 584
Section 114.2: Concurrent calls ............................................................................................................................. 585
Section 114.3: Try/Catch/Finally ............................................................................................................................ 586
Section 114.4: Returning a Task without await ..................................................................................................... 587
Section 114.5: Async/await will only improve performance if it allows the machine to do additional work
587
Section 114.6: Web.config setup to target 4.5 for correct async behaviour .......................................................... 588
Section 114.7: Simple consecutive calls ............................................................................................................... 588
Section 114.8: Blocking on async code can cause deadlocks .............................................................................. 589
Chapter 115: Synchronization Context in Async-Await ........................................................... 591
Section 115.1: Pseudocode for async/await keywords ......................................................................................... 591
Section 115.2: Disabling synchronization context ................................................................................................. 591
Section 115.3: Why SynchronizationContext is so important? .............................................................................. 592
Chapter 116: BackgroundWorker .............................................................................................. 593
Section 116.1: Using a BackgroundWorker to complete a task ............................................................................ 593
Section 116.2: Assigning Event Handlers to a BackgroundWorker ...................................................................... 594
Section 116.3: Creating a new BackgroundWorker instance ................................................................................ 595
Section 116.4: Assigning Properties to a BackgroundWorker ............................................................................... 595
Chapter 117: Task Parallel Library ............................................................................................. 596
Section 117.1: Parallel.ForEach ............................................................................................................................ 596
Section 117.2: Parallel.For .................................................................................................................................... 596
Section 117.3: Parallel.Invoke ............................................................................................................................... 597
Chapter 118: Making a variable thread safe .............................................................................. 598
Section 118.1: Controlling access to a variable in a Parallel.For loop .................................................................. 598
Chapter 119: Lock Statement ..................................................................................................... 599
Section 119.1: Throwing exception in a lock statement ........................................................................................ 599
Section 119.2: Simple usage ................................................................................................................................. 599
Section 119.3: Return in a lock statement ............................................................................................................. 600
Section 119.4: Anti-Patterns and gotchas ............................................................................................................. 600
Section 119.5: Using instances of Object for lock ................................................................................................. 604
Chapter 120: Yield Keyword ....................................................................................................... 605
Section 120.1: Simple Usage ................................................................................................................................ 605
Section 120.2: Correctly checking arguments ....................................................................................................... 605
Section 120.3: Early Termination ........................................................................................................................... 606
Section 120.4: More Pertinent Usage .................................................................................................................... 607
Section 120.5: Lazy Evaluation ............................................................................................................................. 608
Section 120.6: Try finally ........................................................................................................................................ 609
Section 120.7: Eager evaluation ............................................................................................................................ 610
Section 120.8: Using yield to create an IEnumerator<T> when implementing IEnumerable<T>.......................... 610
Section 120.9: Lazy Evaluation Example: Fibonacci Numbers ............................................................................. 611
Section 120.10: The di erence between break and yield break ........................................................................... 612
Section 120.11: Return another Enumerable within a method returning Enumerable .......................................... 613
Chapter 121: Task Parallel Library (TPL) Dataflow Constructs ............................................... 614
Section 121.1: ActionBlock<T> .............................................................................................................................. 614
Section 121.2: BroadcastBlock<T> ....................................................................................................................... 614
Section 121.3: Bu erBlock<T> .............................................................................................................................. 615
Section 121.4: JoinBlock<T1, T2,…> .................................................................................................................... 616
Section 121.5: WriteOnceBlock<T>....................................................................................................................... 617
Section 121.6: BatchedJoinBlock<T1, T2,…> ....................................................................................................... 618
Section 121.7: TransformBlock<TInput, TOutput> ................................................................................................ 619
Section 121.8: TransformManyBlock<TInput, TOutput> ....................................................................................... 619
Section 121.9: BatchBlock<T> .............................................................................................................................. 620
Chapter 122: Functional Programming ..................................................................................... 622
Section 122.1: Func and Action ............................................................................................................................. 622
Section 122.2: Higher-Order Functions ................................................................................................................. 622
Section 122.3: Avoid Null References ................................................................................................................... 622
Section 122.4: Immutability .................................................................................................................................... 624
Section 122.5: Immutable collections .................................................................................................................... 625
Chapter 123: Func delegates...................................................................................................... 626
Section 123.1: Without parameters ....................................................................................................................... 626
Section 123.2: With multiple variables ................................................................................................................... 626
Section 123.3: Lambda & anonymous methods .................................................................................................... 627
Section 123.4: Covariant & Contravariant Type Parameters ................................................................................ 627
Chapter 124: Function with multiple return values .................................................................. 629
Section 124.1: "anonymous object" + "dynamic keyword" solution ....................................................................... 629
Section 124.2: Tuple solution ................................................................................................................................ 629
Section 124.3: Ref and Out Parameters ................................................................................................................ 629
Chapter 125: Binary Serialization .............................................................................................. 631
Section 125.1: Controlling serialization behavior with attributes ........................................................................... 631
Section 125.2: Serialization Binder ........................................................................................................................ 631
Section 125.3: Some gotchas in backward compatibility ...................................................................................... 633
Section 125.4: Making an object serializable ........................................................................................................ 635
Section 125.5: Serialization surrogates (Implementing ISerializationSurrogate) .................................................. 636
Section 125.6: Adding more control by implementing ISerializable ...................................................................... 638
Chapter 126: ICloneable.............................................................................................................. 640
Section 126.1: Implementing ICloneable in a class ............................................................................................... 640
Section 126.2: Implementing ICloneable in a struct .............................................................................................. 640
Chapter 127: IComparable .......................................................................................................... 642
Section 127.1: Sort versions .................................................................................................................................. 642
Chapter 128: Accessing Databases ........................................................................................... 644
Section 128.1: Connection Strings ........................................................................................................................ 644
Section 128.2: Entity Framework Connections ...................................................................................................... 644
Section 128.3: ADO.NET Connections .................................................................................................................. 645
Chapter 129: Using SQLite in C# ............................................................................................... 648
Section 129.1: Creating simple CRUD using SQLite in C# ................................................................................... 648
Section 129.2: Executing Query ............................................................................................................................ 651
Chapter 130: Caching ................................................................................................................. 653
Section 130.1: MemoryCache ............................................................................................................................... 653
Chapter 131: Code Contracts ..................................................................................................... 654
Section 131.1: Postconditions ............................................................................................................................... 654
Section 131.2: Invariants ....................................................................................................................................... 654
Section 131.3: Defining Contracts on Interface ..................................................................................................... 655
Section 131.4: Preconditions ................................................................................................................................. 656
Chapter 132: Code Contracts and Assertions .......................................................................... 658
Section 132.1: Assertions to check logic should always be true ........................................................................... 658
Chapter 133: Structural Design Patterns .................................................................................. 659
Section 133.1: Adapter Design Pattern ................................................................................................................. 659
Chapter 134: Creational Design Patterns .................................................................................. 663
Section 134.1: Singleton Pattern ........................................................................................................................... 663
Section 134.2: Factory Method pattern ................................................................................................................. 664
Section 134.3: Abstract Factory Pattern ................................................................................................................ 667
Section 134.4: Builder Pattern ............................................................................................................................... 669
Section 134.5: Prototype Pattern ........................................................................................................................... 673
Chapter 135: Implementing Decorator Design Pattern ............................................................ 676
Section 135.1: Simulating cafeteria ....................................................................................................................... 676
Chapter 136: Implementing Flyweight Design Pattern ............................................................. 678
Section 136.1: Implementing map in RPG game .................................................................................................. 678
Chapter 137: System.Management.Automation ....................................................................... 681
Section 137.1: Invoke simple synchronous pipeline .............................................................................................. 681
Chapter 138: System.DirectoryServices.Protocols.LdapConnection ..................................... 682
Section 138.1: Authenticated SSL LDAP connection, SSL cert does not match reverse DNS............................. 682
Section 138.2: Super Simple anonymous LDAP ................................................................................................... 683
Chapter 139: C# Authentication handler ................................................................................... 684
Section 139.1: Authentication handler ................................................................................................................... 684
Chapter 140: Pointers ................................................................................................................. 686
Section 140.1: Pointers for array access ............................................................................................................... 686
Section 140.2: Pointer arithmetic ........................................................................................................................... 686
Section 140.3: The asterisk is part of the type ...................................................................................................... 687
Section 140.4: void* ............................................................................................................................................... 687
Section 140.5: Member access using -> ............................................................................................................... 687
Section 140.6: Generic pointers ............................................................................................................................ 688
Chapter 141: Pointers & Unsafe Code ....................................................................................... 689
Section 141.1: Introduction to unsafe code ........................................................................................................... 689
Section 141.2: Accessing Array Elements Using a Pointer ................................................................................... 690
Section 141.3: Compiling Unsafe Code ................................................................................................................. 690
Section 141.4: Retrieving the Data Value Using a Pointer .................................................................................... 691
Section 141.5: Passing Pointers as Parameters to Methods ................................................................................ 692
Chapter 142: How to use C# Structs to create a Union type (Similar to C Unions) ............... 693
Section 142.1: C-Style Unions in C# ..................................................................................................................... 693
Section 142.2: Union Types in C# can also contain Struct fields .......................................................................... 694
Chapter 143: Reactive Extensions (Rx) ..................................................................................... 696
Section 143.1: Observing TextChanged event on a TextBox ............................................................................... 696
Section 143.2: Streaming Data from Database with Observable .......................................................................... 696
Chapter 144: AssemblyInfo.cs Examples.................................................................................. 697
Section 144.1: Global and local AssemblyInfo ...................................................................................................... 697
Section 144.2: [AssemblyVersion] ......................................................................................................................... 697
Section 144.3: Automated versioning .................................................................................................................... 698
Section 144.4: Common fields ............................................................................................................................... 698
Section 144.5: [AssemblyTitle] .............................................................................................................................. 698
Section 144.6: [AssemblyProduct] ......................................................................................................................... 698
Section 144.7: [InternalsVisibleTo] ........................................................................................................................ 698
Section 144.8: [AssemblyConfiguration] ................................................................................................................ 699
Section 144.9: [AssemblyKeyFile] ......................................................................................................................... 699
Section 144.10: Reading Assembly Attributes ...................................................................................................... 699
Chapter 145: Creating a Console Application using a Plain-Text Editor and the C#
Compiler (csc.exe) ...................................................................................................................... 701
Section 145.1: Creating a Console application using a Plain-Text Editor and the C# Compiler ........................... 701
Chapter 146: CLSCompliantAttribute ........................................................................................ 703
Section 146.1: Access Modifier to which CLS rules apply..................................................................................... 703
Section 146.2: Violation of CLS rule: Unsigned types / sbyte ............................................................................... 703
Section 146.3: Violation of CLS rule: Same naming .............................................................................................. 704
Section 146.4: Violation of CLS rule: Identifier _ ................................................................................................... 705
Section 146.5: Violation of CLS rule: Inherit from non CLSComplaint class ......................................................... 705
Chapter 147: ObservableCollection<T>..................................................................................... 706
Section 147.1: Initialize ObservableCollection<T> ................................................................................................ 706
Chapter 148: Hash Functions ..................................................................................................... 707
Section 148.1: PBKDF2 for Password Hashing .................................................................................................... 707
Section 148.2: Complete Password Hashing Solution using Pbkdf2 .................................................................... 707
Section 148.3: MD5 ............................................................................................................................................... 711
Section 148.4: SHA1 ............................................................................................................................................. 711
Section 148.5: SHA256 ......................................................................................................................................... 712
Section 148.6: SHA384 ......................................................................................................................................... 712
Section 148.7: SHA512 ......................................................................................................................................... 713
Chapter 149: Generating Random Numbers in C# ................................................................... 714
Section 149.1: Generate a random int ................................................................................................................... 714
Section 149.2: Generate a random int in a given range ........................................................................................ 714
Section 149.3: Generating the same sequence of random numbers over and over again ................................... 714
Section 149.4: Create multiple random class with di erent seeds simultaneously ............................................... 715
Section 149.5: Generate a Random double .......................................................................................................... 715
Section 149.6: Generate a random character ....................................................................................................... 715
Section 149.7: Generate a number that is a percentage of a max value .............................................................. 715
Chapter 150: Cryptography (System.Security.Cryptography) ................................................. 717
Section 150.1: Modern Examples of Symmetric Authenticated Encryption of a string ......................................... 717
Section 150.2: Introduction to Symmetric and Asymmetric Encryption ................................................................. 728
Section 150.3: Simple Symmetric File Encryption ................................................................................................. 729
Section 150.4: Cryptographically Secure Random Data ....................................................................................... 730
Section 150.5: Password Hashing ......................................................................................................................... 731
Section 150.6: Fast Asymmetric File Encryption ................................................................................................... 731
Chapter 151: ASP.NET Identity .................................................................................................. 736
Section 151.1: How to implement password reset token in asp.net identity using user manager ........................ 736
Chapter 152: Unsafe Code in .NET ............................................................................................ 739
Section 152.1: Using unsafe with arrays ............................................................................................................... 739
Section 152.2: Using unsafe with strings ............................................................................................................... 739
Section 152.3: Unsafe Array Index ........................................................................................................................ 740
Chapter 153: C# Script ................................................................................................................ 741
Section 153.1: Simple code evaluation ................................................................................................................. 741
Chapter 154: Runtime Compile .................................................................................................. 742
Section 154.1: RoslynScript ................................................................................................................................... 742
Section 154.2: CSharpCodeProvider..................................................................................................................... 742
Chapter 155: Interoperability ...................................................................................................... 743
Section 155.1: Import function from unmanaged C++ DLL ................................................................................... 743
Section 155.2: Calling conventions........................................................................................................................ 743
Section 155.3: C++ name mangling ...................................................................................................................... 744
Section 155.4: Dynamic loading and unloading of unmanaged DLLs ................................................................... 744
Section 155.5: Reading structures with Marshal ................................................................................................... 745
Section 155.6: Dealing with Win32 Errors ............................................................................................................. 746
Section 155.7: Pinned Object ................................................................................................................................ 747
Section 155.8: Simple code to expose class for com ............................................................................................ 748
Chapter 156: .NET Compiler Platform (Roslyn) ........................................................................ 750
Section 156.1: Semantic model ............................................................................................................................. 750
Section 156.2: Syntax tree ..................................................................................................................................... 750
Section 156.3: Create workspace from MSBuild project ....................................................................................... 751
Chapter 157: ILGenerator ........................................................................................................... 752
Section 157.1: Creates a DynamicAssembly that contains a UnixTimestamp helper method.............................. 752
Section 157.2: Create method override ................................................................................................................. 753
Chapter 158: T4 Code Generation .............................................................................................. 755
Section 158.1: Runtime Code Generation ............................................................................................................. 755
Chapter 159: Creating Own MessageBox in Windows Form Application .............................. 756
Section 159.1: How to use own created MessageBox control in another Windows Form application .................. 756
Section 159.2: Creating Own MessageBox Control .............................................................................................. 756
Chapter 160: Including Font Resources .................................................................................... 759
Section 160.1: Instantiate 'Fontfamily' from Resources......................................................................................... 759
Section 160.2: Integration method ......................................................................................................................... 759
Section 160.3: Usage with a 'Button' ..................................................................................................................... 759
Chapter 161: Import Google Contacts ....................................................................................... 761
Section 161.1: Requirements ................................................................................................................................ 761
Section 161.2: Source code in the controller ......................................................................................................... 761
Section 161.3: Source code in the view ................................................................................................................ 764
Chapter 162: Garbage Collector in .Net ..................................................................................... 765
Section 162.1: Weak References .......................................................................................................................... 765
Section 162.2: Large Object Heap compaction ..................................................................................................... 766
Chapter 163: Microsoft.Exchange.WebServices ...................................................................... 767
Section 163.1: Retrieve Specified User's Out of O ce Settings ............................................................................ 767
Section 163.2: Update Specific User's Out of O ce Settings ............................................................................... 767
Chapter 164: Windows Communication Foundation ............................................................... 769
Section 164.1: Getting started sample .................................................................................................................. 769
1
Chapter 1: Getting started with C#
Language
Version Release Date
1.0 2002-01-01
1.2 2003-04-01
2.0 2005-09-01
3.0 2007-08-01
4.0 2010-04-01
5.0 2013-06-01
6.0 2015-07-01
7.0 2017-03-07

Section 1.1: Creating a new console application (Visual Studio)


Open Visual Studio
In the toolbar, go to File → New Project
Select the Console Application project type
Open the file Program.cs in the Solution Explorer
Add the following code to Main():

public class Program


{
public static void Main()
{
// Prints a message to the console.
System.Console.WriteLine("Hello, World!");

/* Wait for the user to press a key. This is a common way to prevent
the console window from terminating
and disappearing before the programmer can see the contents
of the window, when the application is run via Start from within VS. */
System.Console.ReadKey();
}
}

In the toolbar, click Debug -> Start Debugging or hit F5 or ctrl + F5 (running without debugger) to run the
program.

Live Demo on ideone

Explanation

class Program is a class declaration. The class Program contains the data and method definitions that your
program uses. Classes generally contain multiple methods. Methods define the behavior of the class. However,
the Program class has only one method: Main.

static void Main() defines the Main method, which is the entry point for all C# programs. The Main method states what
the class does when executed. Only one Main method is allowed per class.

System.Console.WriteLine("Hello, world!"); method prints a given data (in this example, Hello, world!) as an
output in the console window.

INFOBYTE CAREER INSTITUTE 2


System.Console.ReadKey(), ensures that the program won't close immediately after displaying the message. It does
this by waiting for the user to press a key on the keyboard. Any key press from the user will terminate the program.
The program terminates when it has finished the last line of code in the main() method.

Using the command line

To compile via command line use either MSBuild or csc.exe (the C# compiler), both part of the Microsoft Build Tools
package.

To compile this example, run the following command in the same directory where HelloWorld.cs is located:

%WINDIR%\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe HelloWorld.cs

It can also be possible that you have two main methods inside one application. In this case, you have to tell the
compiler which main method to execute by typing the following command in the console.(suppose Class ClassA also
has a main method in the same HelloWorld.cs file in HelloWorld namespace)

%WINDIR%\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe HelloWorld.cs /main:HelloWorld.ClassA

where HelloWorld is namespace

Note: This is the path where .NET framework v4.0 is located in general. Change the path according to your .NET
version. In addition, the directory might be framework instead of framework64 if you're using the 32-bit .NET
Framework. From the Windows Command Prompt, you can list all the csc.exe Framework paths by running the following
commands (the first for 32-bit Frameworks):

dir %WINDIR%\\Microsoft.NET\\Framework\\csc.exe /s/b dir


%WINDIR%\\Microsoft.NET\\Framework64\\csc.exe /s/b

There should now be an executable file named HelloWorld.exe in the same directory. To execute the program from
the command prompt, simply type the executable's name and hit Enter as follows:

HelloWorld.exe

This will produce:

Hello, world!

INFOBYTE CAREER INSTITUTE 3


You may also double click the executable and launch a new console window with the message "Hello, world!"

Section 1.2: Creating a new project in Visual Studio


(console application) and Running it in Debug mode
Download and install Visual Studio. Visual Studio can be downloaded from VisualStudio.com. The
Community edition is suggested, first because it is free, and second because it involves all the general
features and can be extended further.

Open Visual Studio.

Welcome. Go to File → New → Project.

Click Templates → Visual C# → Console Application

INFOBYTE CAREER INSTITUTE 4


After selecting Console Application, Enter a name for your project, and a location to save and press Don't OK .

worry about the Solution name.

Project created. The newly created project will look similar to:

(Always use descriptive names for projects so that they can easily be distinguished from other projects. It
is recommended not to use spaces in project or class name.)

INFOBYTE CAREER INSTITUTE 5


7. Write code. You can now update your Program.cs to present "Hello world!" to the user.

using System;

namespace ConsoleApplication1
{
public class Program
{
public static void Main(string[] args)
{
}
}
}

Add the following two lines to the public static void Main(string[] args) object in Program.cs: (make sure it's inside the
braces)

Console.WriteLine("Hello world!");
Console.Read();

Why Console.Read()? The first line prints out the text "Hello world!" to the console, and the second line waits for a
single character to be entered; in effect, this causes the program to pause execution so that you're able to see the
output while debugging. Without Console.Read();, when you start debugging the application it will just print "Hello
world!" to the console and then immediately close. Your code window should now look like the following:

using System;

namespace ConsoleApplication1
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello world!");
Console.Read();
}
}
}

8. Debug your program. Press the Start Button on the toolbar near the top of the window or press
F5 on your keyboard to run your application. If the button is not present, you can run the program from
the top menu: Debug → Start Debugging. The program will compile and then open a console window. It
should look similar to the following screenshot:

INFOBYTE CAREER INSTITUTE 6


Stop the program. To close the program, just press any key on your keyboard. The Console.Read() we
added was for this same purpose. Another way to close the program is by going to the menu where the
Start button was, and clicking on the Stop button.

Section 1.3: Creating a new program using .NET Core


First install the .NET Core SDK by going through the installation instructions for the platform of your choice:

Windows
OSX
Linux
Docker

After the installation has completed, open a command prompt, or terminal window.

Create a new directory with mkdir hello_world and change into the newly created directory with cd
hello_world.

Create a new console application with dotnet new console. This


will produce two files:

hello_world.csproj

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>

</Project>

Program.cs

using System;

INFOBYTE CAREER INSTITUTE 7


namespace hello_world
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

Restore the needed packages with dotnet restore.

Optional Build the application with dotnet build for Debug or dotnet build -c Release for Release. dotnet run will also run
the compiler and throw build errors, if any are found.

Run the application with dotnet run for Debug or dotnet run
.\bin\Release\netcoreapp1.1\hello_world.dll for Release.

Command Prompt output

INFOBYTE CAREER INSTITUTE 8


Section 1.4: Creating a new program using Mono
First install Mono by going through the install instructions for the platform of your choice as described in their
installation section.

Mono is available for Mac OS X, Windows and Linux.

After installation is done, create a text file, name it HelloWorld.cs and copy the following content into it:

public class Program


{
public static void Main()
{
System.Console.WriteLine("Hello, world!");
System.Console.WriteLine("Press any key to exit..");
System.Console.Read();
}
}

If you are using Windows, run the Mono Command Prompt which is included in the Mono installation and ensures that
the necessary environment variables are set. If on Mac or Linux, open a new terminal.

To compile the newly created file, run the following command in the directory containing HelloWorld.cs:

mcs -out:HelloWorld.exe HelloWorld.cs

The resulting HelloWorld.exe can then be executed with:

mono HelloWorld.exe

which will produce the output:

Hello, world!
Press any key to exit..

Section 1.5: Creating a new query using LinqPad


LinqPad is a great tool that allows you to learn and test features of .Net languages (C#, F# and VB.Net.)

Install LinqPad

Create a new Query ( Ctrl + N )

INFOBYTE CAREER INSTITUTE 9


3. Under language, select "C# statements"

4. Type the following code and hit run ( F5 )

string hw = "Hello World";

hw.Dump(); //or Console.WriteLine(hw);

INFOBYTE CAREER INSTITUTE 10


5. You should see "Hello World" printed out in the results screen.

Now that you have created your first .Net program, go and check out the samples included in LinqPad via the
"Samples" browser. There are many great examples that will show you many different features of the .Net
languages.

Notes:

1. If you click on "IL", you can inspect the IL code that your .net code generates. This is a great learning tool.

INFOBYTE CAREER INSTITUTE 11


When using LINQ to SQL or Linq to Entities you can inspect the SQL that's being generated which is another
great way to learn about LINQ.

Section 1.6: Creating a new project using Xamarin Studio


Download and install Xamarin Studio Community.
Open Xamarin Studio.
Click File → New → Solution.

INFOBYTE CAREER INSTITUTE 12


Click .NET → Console Project and choose C#.
Click Next to proceed.

INFOBYTE CAREER INSTITUTE 13


6. Enter the Project Name and Browse... for a Location to Save and then click Create .

INFOBYTE CAREER INSTITUTE 14


7. The newly created project will look similar to:

8. This is the code in the Text Editor:

INFOBYTE CAREER INSTITUTE 15


using System;

namespace FirstCsharp
{
public class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
}
}
}

9. To run the code, press F5 or click the Play Button as shown below:

10. Following is the Output:

INFOBYTE CAREER INSTITUTE 16


INFOBYTE CAREER INSTITUTE 17
Chapter 2: Literals
Section 2.1: uint literals
uint literals are defined by using the suffix U or u, or by using an integral values within the range of uint:

uint ui = 5U;

Section 2.2: int literals


int literals are defined by simply using integral values within the range of int:

int i = 5;

Section 2.3: sbyte literals


sbyte type has no literal suffix. Integer literals are implicitly converted from int:

sbyte sb = 127;

Section 2.4: decimal literals


decimal literals are defined by using the suffix M or m on a real number:

decimal m = 30.5M;

Section 2.5: double literals


double literals are defined by using the suffix D or d, or by using a real number:

double d = 30.5D;

Section 2.6: float literals


float literals are defined by using the suffix F or f, or by using a real number:

float f = 30.5F;

Section 2.7: long literals


long literals are defined by using the suffix L or l, or by using an integral values within the range of long:

long l = 5L;

Section 2.8: ulong literal


ulong literals are defined by using the suffix UL, ul, Ul, uL, LU, lu, Lu, or lU, or by using an integral values within the range
of ulong:

ulong ul = 5UL;

INFOBYTE CAREER INSTITUTE 18


Section 2.9: string literals
string literals are defined by wrapping the value with double-quotes ":

string s = "hello, this is a string literal";

String literals may contain escape sequences. See String Escape Sequences

Additionally, C# supports verbatim string literals (See Verbatim Strings). These are defined by wrapping the value with
double-quotes ", and prepending it with @. Escape sequences are ignored in verbatim string literals, and all
whitespace characters are included:

string s = @"The path is:


C:\Windows\System32";
//The backslashes and newline are included in the string

Section 2.10: char literals


char literals are defined by wrapping the value with single-quotes ':

char c = 'h';

Character literals may contain escape sequences. See String Escape Sequences

A character literal must be exactly one character long (after all escape sequences have been evaluated). Empty
character literals are not valid. The default character (returned by default(char) or new char()) is '\0', or the NULL
character (not to be confused with the null literal and null references).

Section 2.11: byte literals


byte type has no literal suffix. Integer literals are implicitly converted from int:

byte b = 127;

Section 2.12: short literal


short type has no literal. Integer literals are implicitly converted from int:

short s = 127;

Section 2.13: ushort literal


ushort type has no literal suffix. Integer literals are implicitly converted from int:

ushort us = 127;

Section 2.14: bool literals


bool literals are either true or false;

bool b = true;

INFOBYTE CAREER INSTITUTE 19


Chapter 3: Operators
Parameter Details
operatorSymbol The operator being overloaded, e.g. +, -, /, * OperandType
The type that will be returned by the overloaded operator.
operand1 The first operand to be used in performing the operation.
operand2 The second operand to be used in performing the operation, when doing binary operations.
statements Optional code needed to perform the operation before returning the result.

In C#, an operator is a program element that is applied to one or more operands in an expression or statement.
Operators that take one operand, such as the increment operator (++) or new, are referred to as unary operators.
Operators that take two operands, such as arithmetic operators (+,-,*,/), are referred to as binary operators. One
operator, the conditional operator (?:), takes three operands and is the sole ternary operator in C#.

Section 3.1: Overloadable Operators


C# allows user-defined types to overload operators by defining static member functions using the operator
keyword.
The following example illustrates an implementation of the + operator.

If we have a Complex class which represents a complex number:

public struct Complex


{
public double Real { get; set; }
public double Imaginary { get; set; }
}

And we want to add the option to use the + operator for this class. i.e.:

Complex a = new Complex() { Real = 1, Imaginary = 2 };


Complex b = new Complex() { Real = 4, Imaginary = 8 };
Complex c = a + b;

We will need to overload the + operator for the class. This is done using a static function and the operator keyword:

public static Complex operator +(Complex c1, Complex c2)


{
return new Complex
{
Real = c1.Real + c2.Real,
Imaginary = c1.Imaginary + c2.Imaginary
};
}

Operators such as +, -, *, / can all be overloaded. This also includes Operators that don't return the same type (for
example, == and != can be overloaded, despite returning booleans) The rule below relating to pairs is also enforced here.

Comparison operators have to be overloaded in pairs (e.g. if < is overloaded, > also needs to be overloaded).

A full list of overloadable operators (as well as non-overloadable operators and the restrictions placed on some
overloadable operators) can be seen at MSDN - Overloadable Operators (C# Programming Guide).

INFOBYTE CAREER INSTITUTE 20


Version ≥ 7.0

overloading of operator is was introduced with the pattern matching mechanism of C# 7.0. For details see Pattern
Matching

Given a type Cartesian defined as follows

public class Cartesian


{
public int X { get; }
public int Y { get; }
}

An overloadable operator is could e.g. be defined for Polar coordinates

public static class Polar


{
public static bool operator is(Cartesian c, out double R, out double Theta)
{
R = Math.Sqrt(c.X*c.X + c.Y*c.Y);
Theta = Math.Atan2(c.Y, c.X);
return c.X != 0 || c.Y != 0;
}
}

which can be used like this

var c = Cartesian(3, 4);


if (c is Polar(var R, *))
{
Console.WriteLine(R);
}

(The example is taken from the Roslyn Pattern Matching Documentation)

Section 3.2: Overloading equality operators


Overloading just equality operators is not enough. Under different circumstances, all of the following can be called:

object.Equals and object.GetHashCode


IEquatable<T>.Equals (optional, allows avoiding boxing)
operator == and operator != (optional, allows using operators)

When overriding Equals, GetHashCode must also be overridden. When implementing Equals, there are many
special cases: comparing to objects of a different type, comparing to self etc.

When NOT overridden Equals method and == operator behave differently for classes and structs. For classes just
references are compared, and for structs values of properties are compared via reflection what can negatively affect
performance. == can not be used for comparing structs unless it is overridden.

Generally equality operation must obey the following rules:

Must not throw exceptions.


Reflexivity: A always equals A (may not be true for NULL values in some systems).
Transitvity: if A equals B, and B equals C, then A equals C.
If A equals B, then A and B have equal hash codes.

INFOBYTE CAREER INSTITUTE 21


Inheritance tree independence: if B and C are instances of Class2 inherited from Class1:
Class1.Equals(A,B) must always return the same value as the call to Class2.Equals(A,B).

class Student : IEquatable<Student>


{
public string Name { get; set; } = "";

public bool Equals(Student other)


{
if (ReferenceEquals(other, null)) return false;
if (ReferenceEquals(other, this)) return true;
return string.Equals(Name, other.Name);
}

public override bool Equals(object obj)


{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;

return Equals(obj as Student);


}

public override int GetHashCode()


{
return Name?.GetHashCode() ?? 0;
}

public static bool operator ==(Student left, Student right)


{
return Equals(left, right);
}

public static bool operator !=(Student left, Student right)


{
return !Equals(left, right);
}
}

Section 3.3: Relational Operators


Equals

Checks whether the supplied operands (arguments) are equal

"a" == "b" // Returns false.


"a" == "a" // Returns true.
1 == 0 // Returns false.
1 == 1 // Returns true.
false == true // Returns false.
false == false // Returns true.

Unlike Java, the equality comparison operator works natively with strings.

The equality comparison operator will work with operands of differing types if an implicit cast exists from one to the other.
If no suitable implicit cast exists, you may call an explicit cast or use a method to convert to a compatible type.

1 == 1.0 // Returns true because there is an implicit cast from int to double.
new Object() == 1.0 // Will not compile.

INFOBYTE CAREER INSTITUTE 22


MyStruct.AsInt() == 1 // Calls AsInt() on MyStruct and compares the resulting int with 1.

Unlike Visual Basic.NET, the equality comparison operator is not the same as the equality assignment operator.

var x = new Object();


var y = new Object();
x == y // Returns false, the operands (objects in this case) have different references.
x == x // Returns true, both operands have the same reference.

Not to be confused with the assignment operator (=).

For value types, the operator returns true if both operands are equal in value.
For reference types, the operator returns true if both operands are equal in reference (not value). An exception is that
string objects will be compared with value equality.

Not Equals

Checks whether the supplied operands are not equal.

"a" != "b" // Returns true.


"a" != "a" // Returns false.
1 != 0 // Returns true.
1 != 1 // Returns false.
false != true // Returns true.
false != false // Returns false.

var x = new Object();


var y = new Object();
x != y // Returns true, the operands have different references.
x != x // Returns false, both operands have the same reference.

This operator effectively returns the opposite result to that of the equals ( ==) operator

Greater Than

Checks whether the first operand is greater than the second operand.

3 >5 //Returns false.


1 > 0 //Returns true.
2 > 2 //Return false.

var x = 10;
var y = 15;
x > y //Returns false.
y > x //Returns true.

Less Than

Checks whether the first operand is less than the second operand.

2 <4 //Returns true.


1 < -3 //Returns false.
2 <2 //Return false.

var x = 12;
var y = 22;
x< y //Returns true.
y< x //Returns false.

INFOBYTE CAREER INSTITUTE 23


Greater Than Equal To

Checks whether the first operand is greater than equal to the second operand.

7 >= 8 //Returns false.


0 >= 0 //Returns true.

Less Than Equal To

Checks whether the first operand is less than equal to the second operand.

2 <= 4 //Returns true.


1 <= -3 //Returns false.
1 <= 1 //Returns true.

Section 3.4: Implicit Cast and Explicit Cast Operators


C# allows user-defined types to control assignment and casting through the use of the explicit and implicit keywords.
The signature of the method takes the form:

public static <implicit/explicit> operator <ResultingType>(<SourceType> myType)

The method cannot take any more arguments, nor can it be an instance method. It can, however, access any private
members of type it is defined within.

An example of both an implicit and explicit cast:

public class BinaryImage


{
private bool[] _pixels;

public static implicit operator ColorImage(BinaryImage im)


{
return new ColorImage(im);
}

public static explicit operator bool[](BinaryImage im)


{
return im._pixels;
}
}

Allowing the following cast syntax:

var binaryImage = new BinaryImage();


ColorImage colorImage = binaryImage; // implicit cast, note the lack of type bool[] pixels =
(bool[])binaryImage; // explicit cast, defining the type

The cast operators can work both ways, going from your type and going to your type:

public class BinaryImage


{
public static explicit operator ColorImage(BinaryImage im)
{
return new ColorImage(im);
}

INFOBYTE CAREER INSTITUTE 24


public static explicit operator BinaryImage(ColorImage cm)
{
return new BinaryImage(cm);
}
}

Finally, the as keyword, which can be involved in casting within a type hierarchy, is not valid in this situation. Even after
defining either an explicit or implicit cast, you cannot do:

ColorImage cm = myBinaryImage as ColorImage;

It will generate a compilation error.

Section 3.5: Short-circuiting Operators


By definition, the short-circuiting boolean operators will only evaluate the second operand if the first operand can not
determine the overall result of the expression.

It means that, if you are using && operator as firstCondition && secondCondition it will evaluate secondCondition only
when firstCondition is true and ofcource the overall result will be true only if both of firstOperand and secondOperand are
evaluated to true. This is useful in many scenarios, for example imagine that you want to check whereas your list has
more than three elements but you also have to check if list has been initialized to not run into NullReferenceException.
You can achieve this as below:

bool hasMoreThanThreeElements = myList != null && mList.Count > 3;

mList.Count > 3 will not be checked untill myList != null is met.

Logical AND

is the short-circuiting counterpart of the standard boolean AND ( &) operator.

var x = true;
var y = false;

x && x // Returns true.


x && y // Returns false (y is evaluated).
y && x // Returns false (x is not evaluated).
y && y // Returns false (right y is not evaluated).

Logical OR

is the short-circuiting counterpart of the standard boolean OR (|) operator.

var x = true;
var y = false;

x || x // Returns true (right x is not evaluated).


x || y // Returns true (y is not evaluated).
y || x // Returns true (x and y are evaluated).
y || y // Returns false (y and y are evaluated).

Example usage

if(object != null && object.Property)


// object.Property is never accessed if object is null, because of the short circuit.

INFOBYTE CAREER INSTITUTE 25


Action1();
else
Action2();

Section 3.6: ? : Ternary Operator


Returns one of two values depending on the value of a Boolean expression.

Syntax:

condition ? expression_if_true : expression_if_false;

Example:

string name = "Frank";


Console.WriteLine(name == "Frank" ? "The name is Frank" : "The name is not Frank");

The ternary operator is right-associative which allows for compound ternary expressions to be used. This is done by
adding additional ternary equations in either the true or false position of a parent ternary equation. Care should be taken
to ensure readability, but this can be useful shorthand in some circumstances.

In this example, a compound ternary operation evaluates a clamp function and returns the current value if it's within
the range, the min value if it's below the range, or the max value if it's above the range.

light.intensity = Clamp(light.intensity, minLight, maxLight);

public static float Clamp(float val, float min, float max)


{
return (val < min) ? min : (val > max) ? max : val;
}

Ternary operators can also be nested, such as:

a ? b ? "a is true, b is true" : "a is true, b is false" : "a is false"

// This is evaluated from left to right and can be more easily seen with parenthesis:

a ? (b ? x : y) : z

// Where the result is x if a && b, y if a && !b, and z if !a

When writing compound ternary statements, it's common to use parenthesis or indentation to improve readability.

The types of expression_if_true and expression_if_false must be identical or there must be an implicit conversion from
one to the other.

condition ? 3 : "Not three"; // Doesn't compile because `int` and `string` lack an implicit conversion.

condition ? 3.ToString() : "Not three"; // OK because both possible outputs are strings.

condition ? 3 : 3.5; // OK because there is an implicit conversion from `int` to `double`. The ternary operator will return a
`double`.

condition ? 3.5 : 3; // OK because there is an implicit conversion from `int` to `double`. The ternary operator will return a
`double`.

INFOBYTE CAREER INSTITUTE 26


The type and conversion requirements apply to your own classes too.

public class Car


{}

public class SportsCar : Car


{}

public class SUV : Car


{}

condition ? new SportsCar() : new Car(); // OK because there is an implicit conversion from `SportsCar` to `Car`. The
ternary operator will return a reference of type `Car`.

condition ? new Car() : new SportsCar(); // OK because there is an implicit conversion from `SportsCar` to `Car`. The
ternary operator will return a reference of type `Car`.

condition ? new SportsCar() : new SUV(); // Doesn't compile because there is no implicit conversion from `SportsCar` to SUV or
`SUV` to `SportsCar`. The compiler is not smart enough to realize that both of them have an implicit conversion to `Car`.

condition ? new SportsCar() as Car : new SUV() as Car; // OK because both expressions evaluate to a reference of type `Car`. The
ternary operator will return a reference of type `Car`.

Section 3.7: ?. (Null Conditional Operator)


Version ≥ 6.0

Introduced in C# 6.0, the Null Conditional Operator ?. will immediately return null if the expression on its left-hand side
evaluates to null, instead of throwing a NullReferenceException. If its left-hand side evaluates to a non-null value, it is
treated just like a normal . operator. Note that because it might return null, its return type is always a nullable type. That
means that for a struct or primitive type, it is wrapped into a Nullable<T>.

var bar = Foo.GetBar()?.Value; // will return null if GetBar() returns null


var baz = Foo.GetBar()?.IntegerValue; // baz will be of type Nullable<int>, i.e. int?

This comes handy when firing events. Normally you would have to wrap the event call in an if statement checking for
null and raise the event afterwards, which introduces the possibility of a race condition. Using the Null conditional
operator this can be fixed in the following way:

event EventHandler<string> RaiseMe;


RaiseMe?.Invoke("Event raised");

Section 3.8: "Exclusive or" Operator


The operator for an "exclusive or" (for short XOR) is: ^

This operator returns true when one, but only one, of the supplied bools are true.

true ^ false false Returns true


^ true false ^ Returns true
false true ^ true Returns false
Returns false

INFOBYTE CAREER INSTITUTE 27


Section 3.9: default Operator
Value Type (where T : struct)

The built-in primitive data types, such as char, int, and float, as well as user-defined types declared with struct, or enum.
Their default value is new T() :

default(int) // 0
default(DateTime) // 0001-01-01 12:00:00 AM
default(char) // '\0' This is the "null character", not a zero or a line break.
default(Guid) // 00000000-0000-0000-0000-000000000000
default(MyStruct) // new MyStruct()

// Note: default of an enum is 0, and not the first *key* in that enum // so it could potentially
fail the Enum.IsDefined test
default(MyEnum) // (MyEnum)0

Reference Type (where T : class)

Any class, interface, array or delegate type. Their default value is null :

default(object) // null
default(string) // null
default(MyClass) // null
default(IDisposable) // null
default(dynamic) // null

Section 3.10: Assignment operator '='


The assignment operator = sets thr left hand operand's value to the value of right hand operand, and return that value:

int a = 3; // assigns value 3 to variable a


int b = a = 5; // first assigns value 5 to variable a, then does the same for variable b Console.WriteLine(a = 3 + 4); //
prints 7

Section 3.11: sizeof


Returns an int holding the size of a type* in bytes.

sizeof(bool) // Returns 1.
sizeof(byte) // Returns 1.
sizeof(sbyte) // Returns 1.
sizeof(char) // Returns 2.
sizeof(short) // Returns 2.
sizeof(ushort) // Returns 2.
sizeof(int) // Returns 4.
sizeof(uint) // Returns 4.
sizeof(float) // Returns 4.
sizeof(long) // Returns 8.
sizeof(ulong) // Returns 8.
sizeof(double) // Returns 8.
sizeof(decimal) // Returns 16.

*Only supports certain primitive types in safe context.

INFOBYTE CAREER INSTITUTE 28


In an unsafe context, sizeof can be used to return the size of other primitive types and structs.

public struct CustomType


{
public int value;
}

static void Main()


{
unsafe
{
Console.WriteLine(sizeof(CustomType)); // outputs: 4
}
}

Section 3.12: ?? Null-Coalescing Operator


The Null-Coalescing operator ?? will return the left-hand side when not null. If it is null, it will return the right-hand side.

object foo = null;


object bar = new object();

var c = foo ?? bar;


//c will be bar since foo was null

The ?? operator can be chained which allows the removal of if checks.

//config will be the first non-null returned.


var config = RetrieveConfigOnMachine() ??
RetrieveConfigFromService() ??
new DefaultConfiguration();

Section 3.13: Bit-Shifting Operators


The shift operators allow programmers to adjust an integer by shifting all of its bits to the left or the right. The
following diagram shows the affect of shifting a value to the left by one digit.

Left-Shift

uint value = 15; // 00001111

uint doubled = value << 1; // Result = 00011110 = 30


uint shiftFour = value << 4; // Result = 11110000 = 240

Right-Shift

uint value = 240; // 11110000

uint halved = value >> 1; // Result = 01111000 = 120


uint shiftFour = value >> 4; // Result = 00001111 = 15

Section 3.14: => Lambda operator


Version ≥ 3.0

INFOBYTE CAREER INSTITUTE 29


The => operator has the same precedence as the assignment operator = and is right-associative.

It is used to declare lambda expressions and also it is widely used with LINQ Queries:

string[] words = { "cherry", "apple", "blueberry" };

int shortestWordLength = words.Min((string w) => w.Length); //5

When used in LINQ extensions or queries the type of the objects can usually be skipped as it is inferred by the
compiler:

int shortestWordLength = words.Min(w => w.Length); //also compiles with the same result

The general form of lambda operator is the following:

(input parameters) => expression

The parameters of the lambda expression are specified before => operator, and the actual
expression/statement/block to be executed is to the right of the operator:

// expression
(int x, string s) => s.Length > x

// expression
(int x, int y) => x + y

// statement
(string x) => Console.WriteLine(x)

// block
(string x) => {
x += " says Hello!";
Console.WriteLine(x);
}

This operator can be used to easily define delegates, without writing an explicit method:

delegate void TestDelegate(string s);

TestDelegate myDelegate = s => Console.WriteLine(s + " World");

myDelegate("Hello");

instead of

void MyMethod(string s)
{
Console.WriteLine(s + " World");
}

delegate void TestDelegate(string s);

TestDelegate myDelegate = MyMethod;

myDelegate("Hello");

INFOBYTE CAREER INSTITUTE 30


Section 3.15: Class Member Operators: Null
Conditional Member Access
var zipcode = myEmployee?.Address?.ZipCode;
//returns null if the left operand is null.
//the above is the equivalent of:
var zipcode = (string)null;
if (myEmployee != null && myEmployee.Address != null)
zipcode = myEmployee.Address.ZipCode;

Section 3.16: Class Member Operators: Null


Conditional Indexing
var letters = null;
char? letter = letters?[1];
Console.WriteLine("Second Letter is {0}",letter);
//in the above example rather than throwing an error because letters is null //letter is assigned the
value null

Section 3.17: Postfix and Prefix increment and decrement


Postfix increment X++ will add 1 to x

var x = 42;
x++;
Console.WriteLine(x); // 43

Postfix decrement

X--

will subtract one


var x = 42
x--;
Console.WriteLine(x); // 41

++x is called prefix increment it increments the value of x and then returns x while x++ returns the value of x and then
increments

var x = 42;
Console.WriteLine(++x); // 43
System.out.println(x); // 43

while

var x = 42;
Console.WriteLine(x++); // 42
System.out.println(x); // 43

both are commonly used in for loop

for(int i = 0; i < 10; i++)


{
}

INFOBYTE CAREER INSTITUTE 31


Section 3.18: typeof
Gets System.Type object for a type.

System.Type type = typeof(Point) //System.Drawing.Point


System.Type type = typeof(IDisposable) //System.IDisposable
System.Type type = typeof(Colors) //System.Drawing.Color
System.Type type = typeof(List<>) //System.Collections.Generic.List`1[T]

To get the run-time type, use GetType method to obtain the System.Type of the current instance.

Operator typeof takes a type name as parameter, which is specified at compile time.

public class Animal {}


public class Dog : Animal {}

var animal = new Dog();

Assert.IsTrue(animal.GetType() == typeof(Animal)); // fail, animal is typeof(Dog)


Assert.IsTrue(animal.GetType() == typeof(Dog)); // pass, animal is typeof(Dog)
Assert.IsTrue(animal is Animal); // pass, animal implements Animal

Section 3.19: Binary operators with assignment


C# has several operators that can be combined with an = sign to evaluate the result of the operator and then assign the
result to the original variable.

Example:

x += y

is the same as

x=x+y

Assignment operators:

+=
-=
*=
/=
%=
&=
|=
^=
<<=
>>=

Section 3.20: nameof Operator


Returns a string that represents the unqualified name of a variable, type, or member.

int counter = 10;


nameof(counter); // Returns "counter"
Client client = new Client();

INFOBYTE CAREER INSTITUTE 32


nameof(client.Address.PostalCode)); // Returns "PostalCode"

The nameof operator was introduced in C# 6.0. It is evaluated at compile-time and the returned string value is inserted
inline by the compiler, so it can be used in most cases where the constant string can be used (e.g., the case labels in a
switch statement, attributes, etc...). It can be useful in cases like raising & logging exceptions, attributes, MVC Action links,
etc...

Section 3.21: Class Member Operators: Member Access


var now = DateTime.UtcNow;
//accesses member of a class. In this case the UtcNow property.

Section 3.22: Class Member Operators: Function Invocation


var age = GetAge(dateOfBirth);
//the above calls the function GetAge passing parameter dateOfBirth.

Section 3.23: Class Member Operators: Aggregate Object


Indexing
var letters = "letters".ToCharArray();
char letter = letters[1];
Console.WriteLine("Second Letter is {0}",letter);
//in the above example we take the second character from the array //by calling
letters[1]
//NB: Array Indexing starts at 0; i.e. the first letter would be given by letters[0].

INFOBYTE CAREER INSTITUTE 33


Chapter 4: Conditional Statements
Section 4.1: If-Else Statement
Programming in general often requires a decision or a branch within the code to account for how the code operates
under different inputs or conditions. Within the C# programming language (and most programming languages for
this matter), the simplest and sometimes the most useful way of creating a branch within your program is through
an If-Else statement.

Lets assume we have method (a.k.a. a function) which takes an int parameter which will represent a score up to 100,
and the method will print out a message saying whether we pass or fail.

static void PrintPassOrFail(int score)


{
if (score >= 50) // If score is greater or equal to 50
{
Console.WriteLine("Pass!");
}
else // If score is not greater or equal to 50
{
Console.WriteLine("Fail!");
}
}

When looking at this method, you may notice this line of code ( score >= 50) inside the If statement. This can be seen as a
boolean condition, where if the condition is evaluated to equal true, then the code that is in between the if { } is ran.

For example, if this method was called like this: PrintPassOrFail(60);, the output of the method would be a Console
Print saying Pass! since the parameter value of 60 is greater or equal to 50.

However, if the method was called like: PrintPassOrFail(30);, the output of the method would print out saying Fail!. This is
because the value 30 is not greater or equal to 50, thus the code in between the else { } is ran instead of the If statement.

In this example, we've said that score should go up to 100, which hasn't been accounted for at all. To account for
score not going past 100 or possibly dropping below 0, see the If-Else If-Else Statement example.

Section 4.2: If statement conditions are standard boolean


expressions and values
The following statement

if (conditionA && conditionB && conditionC) //...

is exactly equivalent to

bool conditions = conditionA && conditionB && conditionC; if (conditions) // ...

in other words, the conditions inside the "if" statement just form an ordinary Boolean expression.

A common mistake when writing conditional statements is to explicitly compare to true and false:

INFOBYTE CAREER INSTITUTE 34


if (conditionA == true && conditionB == false && conditionC == true) // ...

This can be rewritten as

if (conditionA && !conditionB && conditionC)

Section 4.3: If-Else If-Else Statement


Following on from the If-Else Statement example, it is now time to introduce the Else If statement. The Else If statement
follows directly after the If statement in the If-Else If-Else structure, but intrinsically has has a similar syntax as the If
statement. It is used to add more branches to the code than what a simple If-Else statement can.

In the example from If-Else Statement, the example specified that the score goes up to 100; however there were
never any checks against this. To fix this, lets modify the method from If-Else Statement to look like this:

static void PrintPassOrFail(int score)


{
if (score > 100) // If score is greater than 100
{
Console.WriteLine("Error: score is greater than 100!");
}
else if (score < 0) // Else If score is less than 0
{
Console.WriteLine("Error: score is less than 0!");
}
else if (score >= 50) // Else if score is greater or equal to 50
{
Console.WriteLine("Pass!");
}
else // If none above, then score must be between 0 and 49
{
Console.WriteLine("Fail!");
}
}

All these statements will run in order from the top all the way to the bottom until a condition has been met. In this new
update of the method, we've added two new branches to now accommodate for the score going out of bounds.

For example, if we now called the method in our code as PrintPassOFail(110);, the output would be a Console Print saying
Error: score is greater than 100!; and if we called the method in our code like PrintPassOrFail(-20);, the output would
say Error: score is less than 0!.

INFOBYTE CAREER INSTITUTE 35


Chapter 5: Equality Operator
Section 5.1: Equality kinds in c# and equality operator
In C#, there are two different kinds of equality: reference equality and value equality. Value equality is the commonly
understood meaning of equality: it means that two objects contain the same values. For example, two integers with the
value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are
two object references, both of which refer to the same object.

object a = new object();


object b = a;
System.Object.ReferenceEquals(a, b); //returns true

For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false
otherwise. For reference types other than string, == returns true if its two operands refer to the same object. For the
string type, == compares the values of the strings.

Numeric equality: True


Console.WriteLine((2 + 2) == 4);

Reference equality: different objects,


same boxed value: False.
object s = 1;
object t = 1;
Console.WriteLine(s == t);

Define some strings: string a =


"hello"; string b = String.Copy(a);
string c = "hello";

Compare string values of a constant and an instance: True


Console.WriteLine(a == b);

Compare string references;


a is a constant but b is an instance: False.
Console.WriteLine((object)a == (object)b);

Compare string references, both constants


have the same value, so string interning
points to same reference: True.
Console.WriteLine((object)a == (object)c);

INFOBYTE CAREER INSTITUTE 36


Chapter 6: Equals and GetHashCode
Section 6.1: Writing a good GetHashCode override
GetHashCode has major performance effects on Dictionary<> and HashTable.

Good GetHashCode Methods

should have an even distribution


every integer should have a roughly equal chance of returning for a random instance
if your method returns the same integer (e.g. the constant '999') for each instance, you'll have bad
performance
should be quick
These are NOT cryptographic hashes, where slowness is a feature
the slower your hash function, the slower your dictionary
must return the same HashCode on two instances that Equals evaluates to true
if they do not (e.g. because GetHashCode returns a random number), items may not be found in a List,
Dictionary, or similar.

A good method to implement GetHashCode is to use one prime number as a starting value, and add the hashcodes of
the fields of the type multiplied by other prime numbers to that:

public override int GetHashCode()


{
unchecked // Overflow is fine, just wrap
{
int hash = 3049; // Start value (prime number).

Suitable nullity checks etc, of course :) hash = hash *


5039 + field1.GetHashCode(); hash = hash * 883 +
field2.GetHashCode(); hash = hash * 9719 +
field3.GetHashCode(); return hash;

}
}

Only the fields which are used in the Equals-method should be used for the hash function.

If you have a need to treat the same type in different ways for Dictionary/HashTables, you can use
IEqualityComparer.

Section 6.2: Default Equals behavior


Equals is declared in the Object class itself.

public virtual bool Equals(Object obj);

By default, Equals has the following behavior:

If the instance is a reference type, then Equals will return true only if the references are the same.

If the instance is a value type, then Equals will return true only if the type and value are the same.

string is a special case. It behaves like a value type.

INFOBYTE CAREER INSTITUTE 37


namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
//areFooClassEqual: False
Foo fooClass1 = new Foo("42");
Foo fooClass2 = new Foo("42");
bool areFooClassEqual = fooClass1.Equals(fooClass2);
Console.WriteLine("fooClass1 and fooClass2 are equal: {0}", areFooClassEqual); //False

//areFooIntEqual: True
int fooInt1 = 42;
int fooInt2 = 42;
bool areFooIntEqual = fooInt1.Equals(fooInt2);
Console.WriteLine("fooInt1 and fooInt2 are equal: {0}", areFooIntEqual);

//areFooStringEqual: True
string fooString1 = "42";
string fooString2 = "42";
bool areFooStringEqual = fooString1.Equals(fooString2);
Console.WriteLine("fooString1 and fooString2 are equal: {0}", areFooStringEqual);
}
}

public class Foo


{
public string Bar { get; }

public Foo(string bar)


{
Bar = bar;
}
}
}

Section 6.3: Override Equals and GetHashCode on


custom types
For a class Person like:

public class Person


{
public string Name { get; set; }
public int Age { get; set; }
public string Clothes { get; set; }
}

var person1 = new Person { Name = "Jon", Age = 20, Clothes = "some clothes" };
var person2 = new Person { Name = "Jon", Age = 20, Clothes = "some other clothes" };

bool result = person1.Equals(person2); //false because it's reference Equals

But defining Equals and GetHashCode as follows:

public class Person


{
public string Name { get; set; }

INFOBYTE CAREER INSTITUTE 38


public int Age { get; set; }
public string Clothes { get; set; }

public override bool Equals(object obj)


{
var person = obj as Person;
if(person == null) return false;
return Name == person.Name && Age == person.Age; //the clothes are not important when comparing two
persons
}

public override int GetHashCode()


{
return Name.GetHashCode()*Age;
}
}

var person1 = new Person { Name = "Jon", Age = 20, Clothes = "some clothes" };
var person2 = new Person { Name = "Jon", Age = 20, Clothes = "some other clothes" }; bool result =

person1.Equals(person2); // result is true

Also using LINQ to make different queries on persons will check both Equals and GetHashCode:

var persons = new List<Person>


{
new Person{ Name = "Jon", Age = 20, Clothes = "some clothes"},
new Person{ Name = "Dave", Age = 20, Clothes = "some other clothes"}, new Person{ Name
= "Jon", Age = 20, Clothes = ""}
};

var distinctPersons = persons.Distinct().ToList();//distinctPersons has Count = 2

Section 6.4: Equals and GetHashCode in IEqualityComparator


For given type Person:

public class Person


{
public string Name { get; set; }
public int Age { get; set; }
public string Clothes { get; set; }
}

List<Person> persons = new List<Person>


{
new Person{ Name = "Jon", Age = 20, Clothes = "some clothes"},
new Person{ Name = "Dave", Age = 20, Clothes = "some other clothes"},
new Person{ Name = "Jon", Age = 20, Clothes = ""}
};

var distinctPersons = persons.Distinct().ToList();// distinctPersons has Count = 3

But defining Equals and GetHashCode into an IEqualityComparator :

public class PersonComparator : IEqualityComparer<Person>


{
public bool Equals(Person x, Person y)
{
return x.Name == y.Name && x.Age == y.Age; //the clothes are not important when comparing

INFOBYTE CAREER INSTITUTE 39


two persons;
}

public int GetHashCode(Person obj) { return obj.Name.GetHashCode() * obj.Age; }


}

var distinctPersons = persons.Distinct(new PersonComparator()).ToList();// distinctPersons has Count = 2

Note that for this query, two objects have been considered equal if both the Equals returned true and the
GetHashCode have returned the same hash code for the two persons.

INFOBYTE CAREER INSTITUTE 40


Chapter 7: Null-Coalescing Operator
Parameter Details
possibleNullObject The value to test for null value. If non null, this value is returned. Must be a nullable type.
The value returned if possibleNullObject is null. Must be the same type as
defaultValue
possibleNullObject.

Section 7.1: Basic usage


Using the null-coalescing operator (??) allows you to specify a default value for a nullable type if the left-hand operand is
null.

string testString = null;


Console.WriteLine("The specified string is - " + (testString ?? "not provided"));

Live Demo on .NET Fiddle

This is logically equivalent to:

string testString = null;


if (testString == null)
{
Console.WriteLine("The specified string is - not provided");
}
else
{
Console.WriteLine("The specified string is - " + testString);
}

or using the ternary operator (?:) operator:

string testString = null;


Console.WriteLine("The specified string is - " + (testString == null ? "not provided" :
testString));

Section 7.2: Null fall-through and chaining


The left-hand operand must be nullable, while the right-hand operand may or may not be. The result will be typed
accordingly.

Non-nullable

int? a = null;
int b = 3;
var output = a ?? b;
var type = output.GetType();

Console.WriteLine($"Output Type :{type}");


Console.WriteLine($"Output value :{output}");

Output:

Type :System.Int32

INFOBYTE CAREER INSTITUTE 41


value :3

View Demo

Nullable

int? a = null;
int? b = null;
var output = a ?? b;

output will be of type int? and equal to b, or null.

Multiple Coalescing

Coalescing can also be done in chains:

int? a = null;
int? b = null;
int c = 3;
var output = a ?? b ?? c;

var type = output.GetType();


Console.WriteLine($"Type :{type}");
Console.WriteLine($"value :{output}");

Output:

Type :System.Int32
value :3

View Demo

Null Conditional Chaining

The null coalescing operator can be used in tandem with the null propagation operator to provide safer access to
properties of objects.

object o = null;
var output = o?.ToString() ?? "Default Value";

Output:

Type :System.String
value :Default Value

View Demo

Section 7.3: Null coalescing operator with method calls


The null coalescing operator makes it easy to ensure that a method that may return null will fall back to a default value.

INFOBYTE CAREER INSTITUTE 42


Without the null coalescing operator:

string name = GetName();

if (name == null)
name = "Unknown!";

With the null coalescing operator:

string name = GetName() ?? "Unknown!";

Section 7.4: Use existing or create new


A common usage scenario that this feature really helps with is when you are looking for an object in a collection and
need to create a new one if it does not already exist.

IEnumerable<MyClass> myList = GetMyList();


var item = myList.SingleOrDefault(x => x.Id == 2) ?? new MyClass { Id = 2 };

Section 7.5: Lazy properties initialization with null


coalescing operator
private List<FooBar> _fooBars;

public List<FooBar> FooBars


{
get { return _fooBars ?? (_fooBars = new List<FooBar>()); }
}

The first time the property .FooBars is accessed the _fooBars variable will evaluate as null, thus falling through to the
assignment statement assigns and evaluates to the resulting value.

Thread safety

This is not thread-safe way of implementing lazy properties. For thread-safe laziness, use the Lazy<T> class built into
the .NET Framework.

C# 6 Syntactic Sugar using expression bodies

Note that since C# 6, this syntax can be simplified using expression body for the property:

private List<FooBar> _fooBars;

public List<FooBar> FooBars => _fooBars ?? ( _fooBars = new List<FooBar>() );

Subsequent accesses to the property will yield the value stored in the _fooBars variable.

Example in the MVVM pattern

This is often used when implementing commands in the MVVM pattern. Instead of initializing the commands
eagerly with the construction of a viewmodel, commands are lazily initialized using this pattern as follows:

private ICommand _actionCommand = null;


public ICommand ActionCommand =>
_actionCommand ?? ( _actionCommand = new DelegateCommand( DoAction ) );

INFOBYTE CAREER INSTITUTE 43


Chapter 8: Null-conditional Operators
Section 8.1: Null-Conditional Operator
The ?. operator is syntactic sugar to avoid verbose null checks. It's also known as the Safe navigation operator.

Class used in the following example:

public class Person


{
public int Age { get; set; }
public string Name { get; set; }
public Person Spouse { get; set; }
}

If an object is potentially null (such as a function that returns a reference type) the object must first be checked for null to
prevent a possible NullReferenceException. Without the null-conditional operator, this would look like:

Person person = GetPerson();

int? age = null;


if (person != null)
age = person.Age;

The same example using the null-conditional operator:

Person person = GetPerson();

var age = person?.Age; // 'age' will be of type 'int?', even if 'person' is not null

Chaining the Operator

The null-conditional operator can be combined on the members and sub-members of an object.

Will be null if either `person` or `person.Spouse` are null int? spouseAge =


person?.Spouse?.Age;

Combining with the Null-Coalescing Operator

The null-conditional operator can be combined with the null-coalescing operator to provide a default value:

spouseDisplayName will be "N/A" if person, Spouse, or Name is null var


spouseDisplayName = person?.Spouse?.Name ?? "N/A";

Section 8.2: The Null-Conditional Index


Similarly to the ?. operator, the null-conditional index operator checks for null values when indexing into a
collection that may be null.

string item = collection?[index];

is syntactic sugar for

string item = null;

INFOBYTE CAREER INSTITUTE 44


if(collection != null)
{
item = collection[index];
}

Section 8.3: Avoiding NullReferenceExceptions


var person = new Person
{
Address = null;
};

var city = person.Address.City; //throws a NullReferenceException var nullableCity =


person.Address?.City; //returns the value of null

This effect can be chained together:

var person = new Person


{
Address = new Address
{
State = new State
{
Country = null
}
}
};

this will always return a value of at least "null" to be stored instead


of throwing a NullReferenceException
var countryName = person?.Address?.State?.Country?.Name;

Section 8.4: Null-conditional Operator can be used with


Extension Method
Extension Method can work on null references, but you can use ?. to null-check anyway.

public class Person


{
public string Name {get; set;}
}

public static class PersonExtensions


{
public static int GetNameLength(this Person person)
{
return person == null ? -1 : person.Name.Length;
}
}

Normally, the method will be triggered for null references, and return -1:

Person person = null;


int nameLength = person.GetNameLength(); // returns -1

Using ?. the method will not be triggered for null references, and the type is int?:

INFOBYTE CAREER INSTITUTE 45


Person person = null;
int? nameLength = person?.GetNameLength(); // nameLength is null.

This behavior is actually expected from the way in which the ?. operator works: it will avoid making instance method calls
for null instances, in order to avoid NullReferenceExceptions. However, the same logic applies to the extension method,
despite the difference on how the method is declared.

For more information on why the extension method is called in the first example, please see the Extension
methods - null checking documentation.

INFOBYTE CAREER INSTITUTE 46


Chapter 9: nameof Operator
The nameof operator allows you to get the name of a variable, type or member in string form without hard-coding it as a
literal.

The operation is evaluated at compile-time, which means that you can rename a referenced identifier, using an IDE's
rename feature, and the name string will update with it.

Section 9.1: Basic usage: Printing a variable name


The nameof operator allows you to get the name of a variable, type or member in string form without hard-coding it as a
literal. The operation is evaluated at compile-time, which means that you can rename, using an IDE's rename feature, a
referenced identifier and the name string will update with it.

var myString = "String Contents";


Console.WriteLine(nameof(myString));

Would output

myString

because the name of the variable is "myString". Refactoring the variable name would change the string.

If called on a reference type, the nameof operator returns the name of the current reference, not the name or type name
of the underlying object. For example:

string greeting = "Hello!";


Object mailMessageBody = greeting;

Console.WriteLine(nameof(greeting)); // Returns "greeting"


Console.WriteLine(nameof(mailMessageBody)); // Returns "mailMessageBody", NOT "greeting"!

Section 9.2: Raising PropertyChanged event


Snippet

public class Person : INotifyPropertyChanged


{
private string _address;

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string propertyName)


{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public string Address


{
get { return _address; }
set
{
if (_address == value)
{

INFOBYTE CAREER INSTITUTE 47


return;
}

_address = value;
OnPropertyChanged(nameof(Address));
}
}
}

...

var person = new Person();


person.PropertyChanged += (s,e) => Console.WriteLine(e.PropertyName); person.Address =

"123 Fake Street";

Console Output

Address

Section 9.3: Argument Checking and Guard Clauses


Prefer

public class Order


{
public OrderLine AddOrderLine(OrderLine orderLine)
{
if (orderLine == null) throw new ArgumentNullException(nameof(orderLine));
...
}
}

Over

public class Order


{
public OrderLine AddOrderLine(OrderLine orderLine)
{
if (orderLine == null) throw new ArgumentNullException("orderLine");
...
}
}

Using the nameof feature makes it easier to refactor method parameters.

Section 9.4: Strongly typed MVC action links


Instead of the usual loosely typed:

@Html.ActionLink("Log in", "UserController", "LogIn")

You can now make action links strongly typed:

@Html.ActionLink("Log in", @typeof(UserController), @nameof(UserController.LogIn))

INFOBYTE CAREER INSTITUTE 48


Now if you want to refactor your code and rename the UserController.LogIn method to UserController.SignIn, you don't need
to worry about searching for all string occurrences. The compiler will do the job.

Section 9.5: Handling PropertyChanged events


Snippet

public class BugReport : INotifyPropertyChanged


{
public string Title { ... }
public BugStatus Status { ... }
}

...

private void BugReport_PropertyChanged(object sender, PropertyChangedEventArgs e)


{
var bugReport = (BugReport)sender;

switch (e.PropertyName)
{
case nameof(bugReport.Title):
Console.WriteLine("{0} changed to {1}", e.PropertyName, bugReport.Title); break;

case nameof(bugReport.Status):
Console.WriteLine("{0} changed to {1}", e.PropertyName, bugReport.Status); break;

}
}

...

var report = new BugReport();


report.PropertyChanged += BugReport_PropertyChanged;

report.Title = "Everything is on fire and broken"; report.Status =


BugStatus.ShowStopper;

Console Output

Title changed to Everything is on fire and broken

Status changed to ShowStopper

Section 9.6: Applied to a generic type parameter


Snippet

public class SomeClass<TItem>


{
public void PrintTypeName()
{
Console.WriteLine(nameof(TItem));
}
}

INFOBYTE CAREER INSTITUTE 49


...

var myClass = new SomeClass<int>();


myClass.PrintTypeName();

Console.WriteLine(nameof(SomeClass<int>));

Console Output

TItem

SomeClass

Section 9.7: Printing a parameter name


Snippet

public void DoSomething(int paramValue)


{
Console.WriteLine(nameof(paramValue));
}

...

int myValue = 10;


DoSomething(myValue);

Console Output

paramValue

Section 9.8: Applied to qualified identifiers


Snippet

Console.WriteLine(nameof(CompanyNamespace.MyNamespace));
Console.WriteLine(nameof(MyClass));
Console.WriteLine(nameof(MyClass.MyNestedClass));
Console.WriteLine(nameof(MyNamespace.MyClass.MyNestedClass.MyStaticProperty));

Console Output

MyNamespace

MyClass

MyNestedClass

MyStaticProperty

INFOBYTE CAREER INSTITUTE 50


Chapter 10: Verbatim Strings
Section 10.1: Interpolated Verbatim Strings
Verbatim strings can be combined with the new String interpolation features found in C#6.

Console.WriteLine($@"Testing \n 1 2 {5 - 2}
New line");

Output:

Testing \n 1 2 3
New line

Live Demo on .NET Fiddle

As expected from a verbatim string, the backslashes are ignored as escape characters. And as expected from an
interpolated string, any expression inside curly braces is evaluated before being inserted into the string at that
position.

Section 10.2: Escaping Double Quotes


Double Quotes inside verbatim strings can be escaped by using 2 sequential double quotes "" to represent one
double quote " in the resulting string.

var str = @"""I don't think so,"" he said.";


Console.WriteLine(str);

Output:

"I don't think so," he said.

Live Demo on .NET Fiddle

Section 10.3: Verbatim strings instruct the compiler to not use


character escapes
In a normal string, the backslash character is the escape character, which instructs the compiler to look at the next
character(s) to determine the actual character in the string. (Full list of character escapes)

In verbatim strings, there are no character escapes (except for "" which is turned into a "). To use a verbatim string, just
prepend a @ before the starting quotes.

This verbatim string

var filename = @"c:\temp\newfile.txt"

Output:

INFOBYTE CAREER INSTITUTE 51


c:\temp\newfile.txt

As opposed to using an ordinary (non-verbatim) string:

var filename = "c:\temp\newfile.txt"

that will output:

c: emp
ewfile.txt

using character escaping. (The \t is replaced with a tab character and the \n is replace with a newline.)

Live Demo on .NET Fiddle

Section 10.4: Multiline Strings


var multiLine = @"This is a

multiline paragraph";

Output:

This is a

multiline paragraph

Live Demo on .NET Fiddle

Multi-line strings that contain double-quotes can also be escaped just as they were on a single line, because they are
verbatim strings.

var multilineWithDoubleQuotes = @"I went to a city named

""San Diego""

during summer vacation.";

Live Demo on .NET Fiddle

It should be noted that the spaces/tabulations at the start of lines 2 and 3 here are actually present in the value of the
variable; check this question for possible solutions.

INFOBYTE CAREER INSTITUTE 52


Chapter 11: Common String Operations
Section 11.1: Formatting a string
Use the String.Format() method to replace one or more items in the string with the string representation of a specified
object:

String.Format("Hello {0} Foo {1}", "World", "Bar") //Hello World Foo Bar

Section 11.2: Correctly reversing a string


Most times when people have to reverse a string, they do it more or less like this:

char[] a = s.ToCharArray();
System.Array.Reverse(a);
string r = new string(a);

However, what these people don't realize is that this is actually wrong.
And I don't mean because of the missing NULL check.

It is actually wrong because a Glyph/GraphemeCluster can consist out of several codepoints (aka. characters).

To see why this is so, we first have to be aware of the fact what the term "character" actually means.

Reference:

Character is an overloaded term than can mean many things.

A code point is the atomic unit of information. Text is a sequence of code points. Each code point is a
number which is given meaning by the Unicode standard.

A grapheme is a sequence of one or more code points that are displayed as a single, graphical unit that a
reader recognizes as a single element of the writing system. For example, both a and ä are graphemes, but
they may consist of multiple code points (e.g. ä may be two code points, one for the base character a followed
by one for the diaresis; but there's also an alternative, legacy, single code point representing this grapheme).
Some code points are never part of any grapheme (e.g. the zero-width non-joiner, or directional overrides).

A glyph is an image, usually stored in a font (which is a collection of glyphs), used to represent graphemes or
parts thereof. Fonts may compose multiple glyphs into a single representation, for example, if the above ä is a
single code point, a font may chose to render that as two separate, spatially overlaid glyphs. For OTF, the
font's GSUB and GPOS tables contain substitution and positioning information to make this work. A font may
contain multiple alternative glyphs for the same grapheme, too.

So in C#, a character is actually a CodePoint.

Which means, if you just reverse a valid string like Les Misérables, which can look like this

string s = "Les Mise\u0301rables";

as a sequence of characters, you will get:

INFOBYTE CAREER INSTITUTE 53


selbaŕesiM seL

As you can see, the accent is on the R character, instead of the e character.
Although string.reverse.reverse will yield the original string if you both times reverse the char array, this kind of
reversal is definitely NOT the reverse of the original string.

You'll need to reverse each GraphemeCluster only.


So, if done correctly, you reverse a string like this:

private static System.Collections.Generic.List<string> GraphemeClusters(string s)


{
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();

System.Globalization.TextElementEnumerator enumerator =
System.Globalization.StringInfo.GetTextElementEnumerator(s);
while (enumerator.MoveNext())
{
ls.Add((string)enumerator.Current);
}

return ls;
}

// this
private static string ReverseGraphemeClusters(string s)
{
if(string.IsNullOrEmpty(s) || s.Length == 1)
return s;

System.Collections.Generic.List<string> ls = GraphemeClusters(s); ls.Reverse();

return string.Join("", ls.ToArray());


}

public static void TestMe()


{
string s = "Les Mise\u0301rables";
// s = "noël";
string r = ReverseGraphemeClusters(s);

This would be wrong:


char[] a = s.ToCharArray();
System.Array.Reverse(a);
string r = new string(a);

System.Console.WriteLine(r);
}

And - oh joy - you'll realize if you do it correctly like this, it will also work for Asian/South-Asian/East-Asian languages
(and French/Swedish/Norwegian, etc.)...

Section 11.3: Padding a string to a fixed length


string s = "Foo";
string paddedLeft = s.PadLeft(5); // paddedLeft = " Foo" (pads with spaces by default) string paddedRight = s.PadRight(6, '+');
// paddedRight = "Foo+++"

INFOBYTE CAREER INSTITUTE 54


string noPadded = s.PadLeft(2); // noPadded = "Foo" (original string is never shortened)

Section 11.4: Getting x characters from the right side of a


string
Visual Basic has Left, Right, and Mid functions that returns characters from the Left, Right, and Middle of a string.
These methods does not exist in C#, but can be implemented with Substring(). They can be implemented as an
extension methods like the following:

public static class StringExtensions


{
<summary>
VB Left function
</summary>
<param name="stringparam"></param>
<param name="numchars"></param>
<returns>Left-most numchars characters</returns>
public static string Left( this string stringparam, int numchars )
{
Handle possible Null or numeric stringparam being passed stringparam
+= string.Empty;

Handle possible negative numchars being passed


numchars = Math.Abs( numchars );

// Validate numchars parameter


if (numchars > stringparam.Length)
numchars = stringparam.Length;

return stringparam.Substring( 0, numchars );


}

<summary>
VB Right function
</summary>
<param name="stringparam"></param>
<param name="numchars"></param>
<returns>Right-most numchars characters</returns>
public static string Right( this string stringparam, int numchars )
{
Handle possible Null or numeric stringparam being passed stringparam
+= string.Empty;

Handle possible negative numchars being passed


numchars = Math.Abs( numchars );

// Validate numchars parameter


if (numchars > stringparam.Length)
numchars = stringparam.Length;

return stringparam.Substring( stringparam.Length - numchars );


}

<summary>
VB Mid function - to end of string
</summary>
<param name="stringparam"></param>
<param name="startIndex">VB-Style startindex, 1st char startindex = 1</param>
<returns>Balance of string beginning at startindex character</returns> public static string
Mid( this string stringparam, int startindex )

INFOBYTE CAREER INSTITUTE 55


{
Handle possible Null or numeric stringparam being passed stringparam
+= string.Empty;

Handle possible negative startindex being passed startindex =


Math.Abs( startindex );

Validate numchars parameter


if (startindex > stringparam.Length)
startindex = stringparam.Length;

C# strings are zero-based, convert passed startindex return


stringparam.Substring( startindex - 1 );
}

<summary>
VB Mid function - for number of characters
</summary>
<param name="stringparam"></param>
<param name="startIndex">VB-Style startindex, 1st char startindex = 1</param>
<param name="numchars">number of characters to return</param>
<returns>Balance of string beginning at startindex character</returns>
public static string Mid( this string stringparam, int startindex, int numchars)
{
Handle possible Null or numeric stringparam being passed stringparam
+= string.Empty;

Handle possible negative startindex being passed startindex =


Math.Abs( startindex );

Handle possible negative numchars being passed


numchars = Math.Abs( numchars );

// Validate numchars parameter


if (startindex > stringparam.Length)
startindex = stringparam.Length;

C# strings are zero-based, convert passed startindex return


stringparam.Substring( startindex - 1, numchars );

}
}

This extension method can be used as follows:

string myLongString = "Hello World!";


string myShortString = myLongString.Right(6); // "World!"
string myLeftString = myLongString.Left(5); // "Hello"
string myMidString1 = myLongString.Left(4); // "lo World"
string myMidString2 = myLongString.Left(2,3); // "ell"

Section 11.5: Checking for empty String using


String.IsNullOrEmpty() and String.IsNullOrWhiteSpace()
string nullString = null;
string emptyString = "";
string whitespaceString = " ";
string tabString = "\t";
string newlineString = "\n";
string nonEmptyString = "abc123";

INFOBYTE CAREER INSTITUTE 56


bool result;

result = String.IsNullOrEmpty(nullString); result = // true


String.IsNullOrEmpty(emptyString); result = // true
String.IsNullOrEmpty(whitespaceString); result = // false
String.IsNullOrEmpty(tabString); result = // false
String.IsNullOrEmpty(newlineString); result = // false
String.IsNullOrEmpty(nonEmptyString); // false

result = String.IsNullOrWhiteSpace(nullString); // true result =


String.IsNullOrWhiteSpace(emptyString); // true result =
String.IsNullOrWhiteSpace(tabString); // true result =
String.IsNullOrWhiteSpace(newlineString); // true
result = String.IsNullOrWhiteSpace(whitespaceString); // true result =
String.IsNullOrWhiteSpace(nonEmptyString); // false

Section 11.6: Trimming Unwanted Characters O the Start


and/or End of Strings
String.Trim()
string x = " Hello World! ";
string y = x.Trim(); // "Hello World!"

string q = "{(Hi!*";
string r = q.Trim( '(', '*', '{' ); // "Hi!"

String.TrimStart() and String.TrimEnd()


string q = "{(Hi*";
string r = q.TrimStart( '{' ); // "(Hi*"
string s = q.TrimEnd( '*' ); // "{(Hi"

Section 11.7: Convert Decimal Number to Binary,Octal


and Hexadecimal Format
1. To convert decimal number to binary format use base 2

Int32 Number = 15;


Console.WriteLine(Convert.ToString(Number, 2)); //OUTPUT : 1111 2. To convert

decimal number to octal format use base 8

int Number = 15;


Console.WriteLine(Convert.ToString(Number, 8)); //OUTPUT : 17 3. To convert

decimal number to hexadecimal format use base 16

var Number = 15;


Console.WriteLine(Convert.ToString(Number, 16)); //OUTPUT : f

Section 11.8: Construct a string from Array


The String.Join method will help us to construct a string From array/list of characters or string. This method accepts two
parameters. The first one is the delimiter or the separator which will help you to separate each element in the array. And
the second parameter is the Array itself.

INFOBYTE CAREER INSTITUTE 57


String from char array:

string delimiter=",";
char[] charArray = new[] { 'a', 'b', 'c' };
string inputString = String.Join(delimiter, charArray);

Output : a,b,c if we change the delimiter as "" then the output will become abc.

String from List of char:

string delimiter = "|";


List<char> charList = new List<char>() { 'a', 'b', 'c' }; string inputString =
String.Join(delimiter, charList);

Output : a|b|c

String from List of Strings:

string delimiter = " ";


List<string> stringList = new List<string>() { "Ram", "is", "a","boy" }; string inputString =
String.Join(delimiter, stringList);

Output : Ram is a boy

String from array of strings:

string delimiter = "_";


string[] stringArray = new [] { "Ram", "is", "a","boy" }; string inputString =
String.Join(delimiter, stringArray);

Output : Ram_is_a_boy

Section 11.9: Formatting using ToString


Usually we are using String.Format method for formatting purpose, the.ToString is usually used for converting other types
to string. We can specify the format along with the ToString method while conversion is taking place, So we can avoid an
additional Formatting. Let Me Explain how it works with different types;

Integer to formatted string:

int intValue = 10;


string zeroPaddedInteger = intValue.ToString("000"); // Output will be "010"
string customFormat = intValue.ToString("Input value is 0"); // output will be "Input value is 10"

double to formatted string:

double doubleValue = 10.456;


string roundedDouble = doubleValue.ToString("0.00"); // output 10.46
string integerPart = doubleValue.ToString("00"); // output 10
string customFormat = doubleValue.ToString("Input value is 0.0"); // Input value is 10.5

Formatting DateTime using ToString

DateTime currentDate = DateTime.Now; // {7/21/2016 7:23:15 PM}


string dateTimeString = currentDate.ToString("dd-MM-yyyy HH:mm:ss"); // "21-07-2016 19:23:15"

INFOBYTE CAREER INSTITUTE 58


string dateOnlyString = currentDate.ToString("dd-MM-yyyy"); // "21-07-2016"
string dateWithMonthInWords = currentDate.ToString("dd-MMMM-yyyy HH:mm:ss"); // "21-July-2016 19:23:15"

Section 11.10: Splitting a String by another string


string str = "this--is--a--complete--sentence";
string[] tokens = str.Split(new[] { "--" }, StringSplitOptions.None);

Result:

[ "this", "is", "a", "complete", "sentence" ]

Section 11.11: Splitting a String by specific character


string helloWorld = "hello world, how is it going?"; string[] parts1 =
helloWorld.Split(',');

//parts1: ["hello world", " how is it going?"]

string[] parts2 = helloWorld.Split(' ');

//parts2: ["hello", "world,", "how", "is", "it", "going?"]

Section 11.12: Getting Substrings of a given string


string helloWorld = "Hello World!";
string world = helloWorld.Substring(6); //world = "World!"
string hello = helloWorld.Substring(0,5); // hello = "Hello"

Substring returns the string up from a given index, or between two indexes (both inclusive).

Section 11.13: Determine whether a string begins with a


given sequence
string HelloWorld = "Hello World";
HelloWorld.StartsWith("Hello"); // true
HelloWorld.StartsWith("Foo"); // false

Finding a string within a string

Using the System.String.Contains you can find out if a particular string exists within a string. The method returns a boolean,
true if the string exists else false.

string s = "Hello World";


bool stringExists = s.Contains("ello"); //stringExists =true as the string contains the substring

Section 11.14: Getting a char at specific index


and enumerating the string
You can use the Substring method to get any number of characters from a string at any given location. However, if you
only want a single character, you can use the string indexer to get a single character at any given index like you

INFOBYTE CAREER INSTITUTE 59


do with an array:

string s = "hello";
char c = s[1]; //Returns 'e'

Notice that the return type is char, unlike the Substring method which returns a string type.

You can also use the indexer to iterate through the characters of the string:

string s = "hello";
foreach (char c in s)
Console.WriteLine(c);
/********* This will print each character on a new line:
h
e
l
l
o
**********/

Section 11.15: Joining an array of strings into a new one


var parts = new[] { "Foo", "Bar", "Fizz", "Buzz"}; var joined =
string.Join(", ", parts);

//joined = "Foo, Bar, Fizz, Buzz"

Section 11.16: Replacing a string within a string


Using the System.String.Replace method, you can replace part of a string with another string.

string s = "Hello World";


s = s.Replace("World", "Universe"); // s = "Hello Universe"

All the occurrences of the search string are replaced.

This method can also be used to remove part of a string, using the String.Empty field:

string s = "Hello World";


s = s.Replace("ell", String.Empty); // s = "Ho World"

Section 11.17: Changing the case of characters within a String


The System.String class supports a number of methods to convert between uppercase and lowercase characters in a
string.

System.String.ToLowerInvariant is used to return a String object converted to lowercase.

System.String.ToUpperInvariant is used to return a String object converted to uppercase.

Note: The reason to use the invariant versions of these methods is to prevent producing unexpected culture-
specific letters. This is explained here in detail.

Example:

string s = "My String";

INFOBYTE CAREER INSTITUTE 60


s = s.ToLowerInvariant(); // "my string"
s = s.ToUpperInvariant(); // "MY STRING"

Note that you can choose to specify a specific Culture when converting to lowercase and uppercase by using the
String.ToLower(CultureInfo) and String.ToUpper(CultureInfo) methods accordingly.

Section 11.18: Concatenate an array of strings into a


single string
The System.String.Join method allows to concatenate all elements in a string array, using a specified separator between
each element:

string[] words = {"One", "Two", "Three", "Four"};


string singleString = String.Join(",", words); // singleString = "One,Two,Three,Four"

Section 11.19: String Concatenation


String Concatenation can be done by using the System.String.Concat method, or (much easier) using the +
operator:

string first = "Hello ";


string second = "World";

string concat = first + second; // concat = "Hello World"


concat = String.Concat(first, second); // concat = "Hello World"

In C# 6 this can be done as follows:

string concat = $"{first},{second}";

INFOBYTE CAREER INSTITUTE 61


Chapter 12: String.Format
Parameter Details
format A composite format string, which defines the way args should be combined into a string.
A sequence of objects to be combined into a string. Since this uses a params argument, you can either use
args
a comma-separated list of arguments or an actual object array.
A collection of ways of formatting objects to strings. Typical values include CultureInfo.InvariantCulture and
provider
CultureInfo.CurrentCulture.

The Format methods are a set of overloads in the System.String class used to create strings that combine objects into
specific string representations. This information can be applied to String.Format, various WriteLine methods as well as
other methods in the .NET framework.

Section 12.1: Since C# 6.0


Version ≥ 6.0

Since C# 6.0 it is possible to use string interpolation in place of String.Format.

string name = "John";


string lastname = "Doe";
Console.WriteLine($"Hello {name} {lastname}!");

Hello John Doe!

More examples for this under the topic C# 6.0 features: String interpolation.

Section 12.2: Places where String.Format is 'embedded' in


the framework
There are several places where you can use String.Format indirectly: The secret is to look for the overload with the
signature string format, params object[] args, e.g.:

Console.WriteLine(String.Format("{0} - {1}", name, value));

Can be replaced with shorter version:

Console.WriteLine("{0} - {1}", name, value);

There are other methods which also use String.Formate.g.:

Debug.WriteLine(); // and Print()


StringBuilder.AppendFormat();

Section 12.3: Create a custom format provider


public class CustomFormat : IFormatProvider, ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (!this.Equals(formatProvider))

INFOBYTE CAREER INSTITUTE 62


{
return null;
}

if (format == "Reverse")
{
return String.Join("", arg.ToString().Reverse());
}

return arg.ToString();
}

public object GetFormat(Type formatType)


{
return formatType==typeof(ICustomFormatter) ? this:null;
}
}

Usage:

String.Format(new CustomFormat(), "-> {0:Reverse} <-", "Hello World");

Output:

-> dlroW olleH <-

Section 12.4: Date Formatting


DateTime date = new DateTime(2016, 07, 06, 18, 30, 14); // Format: year,
month, day hours, minutes, seconds

Console.Write(String.Format("{0:dd}",date));

//Format by Culture info


String.Format(new System.Globalization.CultureInfo("mn-MN"),"{0:dddd}",date);
Version ≥ 6.0

Console.Write($"{date:ddd}");

output :

06
Лхагва
06

Specifier Meaning Sample Result


d Date {0 :d} 7/6/2016
dd Day, zero-padded {0 :dd} 06
ddd Short day name {0 :ddd} Wed
dddd Full day name {0 :dddd} Wednesday
D Long date {0 :D} Wednesday, July 6, 2016
f Full date and time, short {0 :f} Wednesday, July 6, 2016 6:30 PM
ff Second fractions, 2 digits {0 :ff} 20
fff Second fractions, 3 digits {0 :fff} 201
ffff Second fractions, 4 digits {0 :ffff} 2016
F Full date and time, long {0 :F} Wednesday, July 6, 2016 6:30:14 PM

INFOBYTE CAREER INSTITUTE 63


g Default date and time { 0:g} 7/6/2016 6:30 PM
gg Era { 0:gg} A.D
hh Hour (2 digits, 12H) { 0:hh} 06
HH Hour (2 digits, 24H) { 0:HH} 18
M Month and day { 0:M} July 6
mm Minutes, zero-padded { 0:mm} 30
MM Month, zero-padded { 0:MM} 07
MMM 3-letter month name { 0:MMM} Jul
MMMM Full month name { 0:MMMM} July
ss Seconds { 0:ss} 14
r RFC1123 date { 0:r} Wed, 06 Jul 2016 18:30:14 GMT
s Sortable date string { 0:s} 2016-07-06T18:30:14
t Short time { 0:t} 6:30 PM
T Long time { 0:T} 6:30:14 PM
tt AM/PM { 0:tt} PM
u Universal sortable local time { 0:u} 2016-07-06 18:30:14Z
U Universal GMT { 0:U} Wednesday, July 6, 2016 9:30:14 AM
Y Month and year { 0:Y} July 2016
yy 2 digit year { 0:yy} 16
yyyy 4 digit year { 0:yyyy} 2016
zz 2 digit timezone offset { 0:zz} +09
zzz full time zone offset { 0:zzz} +09:00

Section 12.5: Currency Formatting


The "c" (or currency) format specifier converts a number to a string that represents a currency amount.

string.Format("{0:c}", 112.236677) // $112.23 - defaults to system

Precision

Default is 2. Use c1, c2, c3 and so on to control precision.

string.Format("{0:C1}", 112.236677) //$112.2 string.Format("{0:C3}",


112.236677) //$112.237 string.Format("{0:C4}", 112.236677)
//$112.2367 string.Format("{0:C9}", 112.236677) //$112.236677000

Currency Symbol

1. Pass CultureInfo instance to use custom culture symbol.

string.Format(new CultureInfo("en-US"), "{0:c}", 112.236677); //$112.24 string.Format(new


CultureInfo("de-DE"), "{0:c}", 112.236677); //112,24 € string.Format(new CultureInfo("hi-IN"),
"{0:c}", 112.236677); // 112.24

2. Use any string as currency symbol. Use NumberFormatInfo as to customize currency symbol.

NumberFormatInfo nfi = new CultureInfo( "en-US", false ).NumberFormat; nfi =


(NumberFormatInfo) nfi.Clone(); nfi.CurrencySymbol = "?";

INFOBYTE CAREER INSTITUTE 64


string.Format(nfi, "{0:C}", 112.236677); //?112.24
nfi.CurrencySymbol = "?%^&";
string.Format(nfi, "{0:C}", 112.236677); //?%^&112.24

Position of Currency Symbol

Use CurrencyPositivePattern for positive values and CurrencyNegativePattern for negative values.

NumberFormatInfo nfi = new CultureInfo( "en-US", false ).NumberFormat;


nfi.CurrencyPositivePattern = 0;
string.Format(nfi, "{0:C}", 112.236677); //$112.24 - default
nfi.CurrencyPositivePattern = 1;
string.Format(nfi, "{0:C}", 112.236677); //112.24$
nfi.CurrencyPositivePattern = 2;
string.Format(nfi, "{0:C}", 112.236677); //$ 112.24
nfi.CurrencyPositivePattern = 3;
string.Format(nfi, "{0:C}", 112.236677); //112.24 $

Negative pattern usage is the same as positive pattern. A lot more use cases please refer to original link.

Custom Decimal Separator


NumberFormatInfo nfi = new CultureInfo( "en-US", false ).NumberFormat;
nfi.CurrencyPositivePattern = 0;
nfi.CurrencyDecimalSeparator = "..";
string.Format(nfi, "{0:C}", 112.236677); //$112..24

Section 12.6: Using custom number format


NumberFormatInfo can be used for formatting both integer and float numbers.

// invariantResult is "1,234,567.89"
var invarianResult = string.Format(CultureInfo.InvariantCulture, "{0:#,###,##}", 1234567.89);

NumberFormatInfo is one of classes that implement IFormatProvider var


customProvider = new NumberFormatInfo
{
NumberDecimalSeparator = "_NS_", // will be used instead of ','
NumberGroupSeparator = "_GS_", // will be used instead of '.'
};

customResult is "1_GS_234_GS_567_NS_89"
var customResult = string.Format(customProvider, "{0:#,###.##}", 1234567.89);

Section 12.7: Align left/ right, pad with spaces


The second value in the curly braces dictates the length of the replacement string. By adjusting the second value to be
positive or negative, the alignment of the string can be changed.

string.Format("LEFT: string: ->{0,-5}<- int: ->{1,-5}<-", "abc", 123);


string.Format("RIGHT: string: ->{0,5}<- int: ->{1,5}<-", "abc", 123);

Output:

LEFT: string: ->abc <- int: ->123 <-


RIGHT: string: -> abc<- int: -> 123<-

INFOBYTE CAREER INSTITUTE 65


Section 12.8: Numeric formats
// Integral types as hex
string.Format("Hexadecimal: byte2: {0:x2}; byte4: {0:X4}; char: {1:x2}", 123, (int)'A');

// Integers with thousand separators


string.Format("Integer, thousand sep.: {0:#,#}; fixed length: >{0,10:#,#}<", 1234567);

// Integer with leading zeroes


string.Format("Integer, leading zeroes: {0:00}; ", 1);

// Decimals
string.Format("Decimal, fixed precision: {0:0.000}; as percents: {0:0.00%}", 0.12);

Output:

Hexadecimal: byte2: 7b; byte4: 007B; char: 41


Integer, thousand sep.: 1,234,567; fixed length: > 1,234,567<
Integer, leading zeroes: 01;
Decimal, fixed precision: 0.120; as percents: 12.00%

Section 12.9: ToString()


The ToString() method is present on all reference object types. This is due to all reference types being derived from
Object which has the ToString() method on it. The ToString() method on the object base class returns the type name.
The fragment below will print out "User" to the console.

public class User


{
public string Name { get; set; }
public int Id { get; set; }
}

...

var user = new User {Name = "User1", Id = 5};


Console.WriteLine(user.ToString());

However, the class User can also override ToString() in order to alter the string it returns. The code fragment below
prints out "Id: 5, Name: User1" to the console.

public class User


{
public string Name { get; set; }
public int Id { get; set; }
public override ToString()
{
return string.Format("Id: {0}, Name: {1}", Id, Name);
}
}

...

var user = new User {Name = "User1", Id = 5};


Console.WriteLine(user.ToString());

INFOBYTE CAREER INSTITUTE 66


Section 12.10: Escaping curly brackets inside a
String.Format() expression
string outsidetext = "I am outside of bracket";
string.Format("{{I am in brackets!}} {0}", outsidetext);

//Outputs "{I am in brackets!} I am outside of bracket"

Section 12.11: Relationship with ToString()


While the String.Format() method is certainly useful in formatting data as strings, it may often be a bit overkill,
especially when dealing with a single object as seen below :

String.Format("{0:C}", money); // yields "$42.00"

An easier approach might be to simply use the ToString() method available on all objects within C#. It supports all of the
same standard and custom formatting strings, but doesn't require the necessary parameter mapping as there will only be
a single argument :

money.ToString("C"); // yields "$42.00"

Caveats & Formatting Restrictions

While this approach may be simpler in some scenarios, the ToString() approach is limited with regards to adding left or
right padding like you might do within the String.Format() method :

String.Format("{0,10:C}", money); // yields " $42.00"

In order to accomplish this same behavior with the ToString() method, you would need to use another method like
PadLeft() or PadRight() respectively :

money.ToString("C").PadLeft(10); // yields " $42.00"

INFOBYTE CAREER INSTITUTE 67


Chapter 13: String Concatenate
Section 13.1: + Operator
string s1 = "string1";
string s2 = "string2";

string s3 = s1 + s2; // "string1string2"

Section 13.2: Concatenate strings


using System.Text.StringBuilder
Concatenating strings using a StringBuilder can offer performance advantages over simple string concatenation using +.
This is due to the way memory is allocated. Strings are reallocated with each concatenation, StringBuilders allocate
memory in blocks only reallocating when the current block is exhausted. This can make a huge difference when doing a
lot of small concatenations.

StringBuilder sb = new StringBuilder();


for (int i = 1; i <= 5; i++)
{
sb.Append(i);
sb.Append(" ");
}
Console.WriteLine(sb.ToString()); // "1 2 3 4 5 "

Calls to Append() can be daisy chained, because it returns a reference to the StringBuilder:

StringBuilder sb = new StringBuilder();


sb.Append("some string ")
.Append("another string");

Section 13.3: Concat string array elements using String.Join


The String.Join method can be used to concatenate multiple elements from a string array.

string[] value = {"apple", "orange", "grape", "pear"}; string separator = ", ";

string result = String.Join(separator, value, 1, 2);


Console.WriteLine(result);

Produces the following output: "orange, grape"

This example uses the String.Join(String, String[], Int32, Int32) overload, which specifies the start index and count on top
of the separator and value.

If you do not wish to use the startIndex and count overloads, you can join all string given. Like this:

string[] value = {"apple", "orange", "grape", "pear"}; string separator = ", ";

string result = String.Join(separator, value);


Console.WriteLine(result);

INFOBYTE CAREER INSTITUTE 68


which will produce;

apple, orange, grape, pear

Section 13.4: Concatenation of two strings using $


$ provides an easy and a concise method to concatenate multiple strings.

var str1 = "text1";


var str2 = " ";
var str3 = "text3";
string result2 = $"{str1}{str2}{str3}"; //"text1 text3"

INFOBYTE CAREER INSTITUTE 69


Chapter 14: String Manipulation
Section 14.1: Replacing a string within a string
Using the System.String.Replace method, you can replace part of a string with another string.

string s = "Hello World";


s = s.Replace("World", "Universe"); // s = "Hello Universe"

All the occurrences of the search string are replaced:

string s = "Hello World";


s = s.Replace("l", "L"); // s = "HeLLo WorLD"

String.Replace can also be used to remove part of a string, by specifying an empty string as the replacement value:

string s = "Hello World";


s = s.Replace("ell", String.Empty); // s = "Ho World"

Section 14.2: Finding a string within a string


Using the System.String.Contains you can find out if a particular string exists within a string. The method returns a boolean,
true if the string exists else false.

string s = "Hello World";


bool stringExists = s.Contains("ello"); //stringExists =true as the string contains the substring

Using the System.String.IndexOf method, you can locate the starting position of a substring within an existing string.

Note the returned position is zero-based, a value of -1 is returned if the substring is not found.

string s = "Hello World";


int location = s.IndexOf("ello"); // location = 1

To find the first location from the end of a string, use the System.String.LastIndexOf method:

string s = "Hello World";


int location = s.LastIndexOf("l"); // location = 9

Section 14.3: Removing (Trimming) white-space from a string


The System.String.Trim method can be used to remove all leading and trailing white-space characters from a string:

string s = " String with spaces at both ends ";


s = s.Trim(); // s = "String with spaces at both ends"

In addition:

To remove white-space only from the beginning of a string use: System.String.TrimStart

To remove white-space only from the end of a string use: System.String.TrimEnd

INFOBYTE CAREER INSTITUTE 70


Substring to extract part of a string.

The System.String.Substring method can be used to extract a portion of the string.

string s ="A portion of word that is retained";


s=str.Substring(26); //s="retained"

s1 = s.Substring(0,5); //s="A por"

Section 14.4: Splitting a string using a delimiter


Use the System.String.Split method to return a string array that contains substrings of the original string, split based on a
specified delimiter:

string sentence = "One Two Three Four";


string[] stringArray = sentence.Split(' ');

foreach (string word in stringArray)


{
Console.WriteLine(word);
}

Output:

One
Two
Three
Four

Section 14.5: Concatenate an array of strings into a single


string
The System.String.Join method allows to concatenate all elements in a string array, using a specified separator between
each element:

string[] words = {"One", "Two", "Three", "Four"};


string singleString = String.Join(",", words); // singleString = "One,Two,Three,Four"

Section 14.6: String Concatenation


String Concatenation can be done by using the System.String.Concat method, or (much easier) using the +
operator:

string first = "Hello ";


string second = "World";

string concat = first + second; // concat = "Hello World"


concat = String.Concat(first, second); // concat = "Hello World"

Section 14.7: Changing the case of characters within a String


The System.String class supports a number of methods to convert between uppercase and lowercase characters in a
string.

INFOBYTE CAREER INSTITUTE 71


System.String.ToLowerInvariant is used to return a String object converted to lowercase.

System.String.ToUpperInvariant is used to return a String object converted to uppercase.

Note: The reason to use the invariant versions of these methods is to prevent producing unexpected culture-
specific letters. This is explained here in detail.

Example:

string s = "My String";


s = s.ToLowerInvariant(); // "my string"
s = s.ToUpperInvariant(); // "MY STRING"

Note that you can choose to specify a specific Culture when converting to lowercase and uppercase by using the
String.ToLower(CultureInfo) and String.ToUpper(CultureInfo) methods accordingly.

INFOBYTE CAREER INSTITUTE 72


Chapter 15: String Interpolation
Section 15.1: Format dates in strings
var date = new DateTime(2015, 11, 11);
var str = $"It's {date:MMMM d, yyyy}, make a wish!";
System.Console.WriteLine(str);

You can also use the DateTime.ToString method to format the DateTime object. This will produce the same output as the
code above.

var date = new DateTime(2015, 11, 11);


var str = date.ToString("MMMM d, yyyy");
str = "It's " + str + ", make a wish!";
Console.WriteLine(str);

Output:

It's November 11, 2015, make a wish!

Live Demo on .NET Fiddle

Live Demo using DateTime.ToString

Note: MM stands for months and mm for minutes. Be very careful when using these as mistakes can
introduce bugs that may be difficult to discover.

Section 15.2: Padding the output


String can be formatted to accept a padding parameter that will specify how many character positions the inserted string
will use :

${value, padding}

NOTE: Positive padding values indicate left padding and negative padding values indicate right padding.

Left Padding

A left padding of 5 (adds 3 spaces before the value of number, so it takes up a total of 5 character positions in the
resulting string.)

var number = 42;


var str = $"The answer to life, the universe and everything is {number, 5}.";
//str is "The answer to life, the universe and everything is 42.";
// ^^^^^
System.Console.WriteLine(str);

Output:

INFOBYTE CAREER INSTITUTE 73


The answer to life, the universe and everything is 42.

Live Demo on .NET Fiddle

Right Padding

Right padding, which uses a negative padding value, will add spaces to the end of the current value.

var number = 42;


var str = $"The answer to life, the universe and everything is ${number, -5}."; //str is "The answer to life, the
universe and everything is 42 .";
// ^^^^^
System.Console.WriteLine(str);

Output:

The answer to life, the universe and everything is 42 .

Live Demo on .NET Fiddle

Padding with Format Specifiers

You can also use existing formatting specifiers in conjunction with padding.

var number = 42;


var str = $"The answer to life, the universe and everything is ${number, 5:f1}"; //str is "The answer to life, the
universe and everything is 42.1 ";
// ^^^^^

Live Demo on .NET Fiddle

Section 15.3: Expressions


Full expressions can also be used in interpolated strings.

var StrWithMathExpression = $"1 + 2 = {1 + 2}"; // -> "1 + 2 = 3"

string world = "world";


var StrWithFunctionCall = $"Hello, {world.ToUpper()}!"; // -> "Hello, WORLD!"

Live Demo on .NET Fiddle

Section 15.4: Formatting numbers in strings


You can use a colon and the standard numeric format syntax to control how numbers are formatted.

var decimalValue = 120.5;

var asCurrency = $"It costs {decimalValue:C}";


// String value is "It costs $120.50" (depending on your local currency settings)

var withThreeDecimalPlaces = $"Exactly {decimalValue:F3}"; // String value is


"Exactly 120.500"

var integerValue = 57;

INFOBYTE CAREER INSTITUTE 74


var prefixedIfNecessary = $"{integerValue:D5}";
// String value is "00057"

Live Demo on .NET Fiddle

Section 15.5: Simple Usage


var name = "World";
var str = $"Hello, {name}!";
//str now contains: "Hello, World!";

Behind the scenes

Internally this

$"Hello, {name}!"

Will be compiled to something like this:

string.Format("Hello, {0}!", name);

INFOBYTE CAREER INSTITUTE 75


Chapter 16: String Escape Sequences
Section 16.1: Escaping special symbols in string literals
Backslash

The filename will be c:\myfile.txt in both cases string filename =


"c:\\myfile.txt";
string filename = @"c:\myfile.txt";

The second example uses a verbatim string literal, which doesn't treat the backslash as an escape character.

Quotes

string text = "\"Hello World!\", said the quick brown fox.";


string verbatimText = @"""Hello World!"", said the quick brown fox.";

Both variables will contain the same text.

"Hello World!", said the quick brown fox.

Newlines

Verbatim string literals can contain newlines:

string text = "Hello\r\nWorld!";


string verbatimText = @"Hello
World!";

Both variables will contain the same text.

Section 16.2: Unicode character escape sequences


string sqrt = "\\u221A"; // √
string emoji = "\\U0001F601"; // ?
string text = "\\u0022Hello World\\u0022"; // "Hello World"
string variableWidth = "\\x22Hello World\\x22"; // "Hello World"

Section 16.3: Escaping special symbols in character literals


Apostrophes

char apostrophe = '\'';

Backslash

char oneBackslash = '\\';

Section 16.4: Using escape sequences in identifiers


Escape sequences are not restricted to string and char literals.

INFOBYTE CAREER INSTITUTE 76


Suppose you need to override a third-party method:

protected abstract IEnumerable<Texte> ObtenirŒuvres();

and suppose the character Œ is not available in the character encoding you use for your C# source files. You are
lucky, it is permitted to use escapes of the type \u#### or \U######## in identifiers in the code. So it is legal to write:

protected override IEnumerable<Texte> Obtenir\u0152uvres()


{
// ...
}

and the C# compiler will know Œ and \u0152 are the same character.

(However, it might be a good idea to switch to UTF-8 or a similar encoding that can handle all characters.)

Section 16.5: Unrecognized escape sequences


produce compile-time errors
The following examples will not compile:

string s = "\c";
char c = '\c';

Instead, they will produce the error Unrecognized escape sequence at compile time.

INFOBYTE CAREER INSTITUTE 77


Chapter 17: StringBuilder
Section 17.1: What a StringBuilder is and when to use one
A StringBuilder represents a series of characters, which unlike a normal string, are mutable. Often times there is a need to
modify strings that we've already made, but the standard string object is not mutable. This means that each time a string
is modified, a new string object needs to be created, copied to, and then reassigned.

string myString = "Apples";


mystring += " are my favorite fruit";

In the above example, myString initially only has the value "Apples". However, when we concatenate `" are my favorite
fruit"', what the string class does internally needs to do involves:

Creating a new array of characters equal to the length of myString and the new string we are appending.
Copying all of the characters of myString into the beginning of our new array and copying the new string into the
end of the array.
Create a new string object in memory and reassign it to myString.

For a single concatenation, this is relatively trivial. However, what if needed to perform many append operations, say,
in a loop?

String myString = "";


for (int i = 0; i < 10000; i++)
myString += " "; // puts 10,000 spaces into our string

Due to the repeated copying and object creation, this will bring significantly degrade the performance of our
program. We can avoid this by instead using a StringBuilder.

StringBuilder myStringBuilder = new StringBuilder(); for (int i = 0; i <


10000; i++)
myStringBuilder.Append(' ');

Now when the same loop is run, the performance and speed of the execution time of the program will be significantly
faster than using a normal string. To make the StringBuilder back into a normal string, we can simply call the ToString()
method of StringBuilder.

However, this isn't the only optimization StringBuilder has. In order to further optimize functions, we can take
advantage of other properties that help improve performance.

StringBuilder sb = new StringBuilder(10000); // initializes the capacity to 10000

If we know in advance how long our StringBuilder needs to be, we can specify its size ahead of time, which will prevent
it from needing to resize the character array it has internally.

sb.Append('k', 2000);

Though using StringBuilder for appending is much faster than a string, it can run even faster if you only need to add a
single character many times.

Once you have completed building your string, you may use the ToString() method on the StringBuilder to convert it to a
basic string. This is often necessary because the StringBuilder class does not inherit from string.

INFOBYTE CAREER INSTITUTE 78


For example, here is how you can use a StringBuilder to create a string:

string RepeatCharacterTimes(char character, int times)


{
StringBuilder builder = new StringBuilder("");
for (int counter = 0; counter < times; counter++)
{
//Append one instance of the character to the StringBuilder.
builder.Append(character);
}
//Convert the result to string and return it.
return builder.ToString();
}

In conclusion, StringBuilder should be used in place of string when many modifications to a string need to be made
with performance in mind.

Section 17.2: Use StringBuilder to create string from a large


number of records
public string GetCustomerNamesCsv()
{
List<CustomerData> customerDataRecords = GetCustomerData(); // Returns a large number of records, say, 10000+

StringBuilder customerNamesCsv = new StringBuilder(); foreach


(CustomerData record in customerDataRecords) {

customerNamesCsv
.Append(record.LastName)
.Append(',')
.Append(record.FirstName)
.Append(Environment.NewLine);
}

return customerNamesCsv.ToString();
}

INFOBYTE CAREER INSTITUTE 79


Chapter 18: Regex Parsing
Name Details
Pattern The string pattern that has to be used for the lookup. For more information: msdn
The common options in here are Singleline and Multiline. They are changing the
RegexOptions
behaviour of pattern-elements like the dot (.) which won't cover a NewLine (\n) in
[Optional]
Multiline-Mode but in SingleLine-Mode. Default behaviour: msdn
Where patterns are getting more complex the lookup can consume more time. This is the
Timeout [Optional]
passed timeout for the lookup just as known from network-programming.

Section 18.1: Single match


using System.Text.RegularExpressions;

string pattern = ":(.*?):";


string lookup = "--:text in here:--";

// Instanciate your regex object and pass a pattern to it


Regex rgxLookup = new Regex(pattern, RegexOptions.Singleline, TimeSpan.FromSeconds(1));
Get the match from your regex-object Match
mLookup = rgxLookup.Match(lookup);

The group-index 0 always covers the full pattern.


Matches inside parentheses will be accessed through the index 1 and above. string found =
mLookup.Groups[1].Value;

Result:

found = "text in here"

Section 18.2: Multiple matches


using System.Text.RegularExpressions;

List<string> found = new List<string>();


string pattern = ":(.*?):";
string lookup = "--:text in here:--:another one:-:third one:---!123:fourth:";

// Instanciate your regex object and pass a pattern to it


Regex rgxLookup = new Regex(pattern, RegexOptions.Singleline, TimeSpan.FromSeconds(1)); MatchCollection
mLookup = rgxLookup.Matches(lookup);

foreach(Match match in mLookup)


{
found.Add(match.Groups[1].Value);
}

Result:

found = new List<string>() { "text in here", "another one", "third one", "fourth" }

INFOBYTE CAREER INSTITUTE 80


Chapter 19: DateTime Methods
Section 19.1: DateTime Formatting
Standard DateTime Formatting

DateTimeFormatInfo specifies a set of specifiers for simple date and time formatting. Every specifier correspond to a
particular DateTimeFormatInfo format pattern.

//Create datetime
DateTime dt = new DateTime(2016,08,01,18,50,23,230);

var t = String.Format("{0:t}", dt); // "6:50 PM" ShortTime


var d = String.Format("{0:d}", dt); // "8/1/2016" ShortDate
var T = String.Format("{0:T}", dt); // "6:50:23 PM" LongTime
var D = String.Format("{0:D}", dt); // "Monday, August 1, 2016" LongDate
var f = String.Format("{0:f}", dt); // "Monday, August 1, 2016 6:50 PM" LongDate+ShortTime
var F = String.Format("{0:F}", dt); // "Monday, August 1, 2016 6:50:23 PM" FullDateTime
var g = String.Format("{0:g}", dt); // "8/1/2016 6:50 PM" ShortDate+ShortTime
var G = String.Format("{0:G}", dt); // "8/1/2016 6:50:23 PM" ShortDate+LongTime
var m = String.Format("{0:m}", dt); // "August 1" MonthDay
var y = String.Format("{0:y}", dt); // "August 2016" YearMonth
var r = String.Format("{0:r}", dt); // "SMon, 01 Aug 2016 18:50:23 GMT" RFC1123
var s = String.Format("{0:s}", dt); // "2016-08-01T18:50:23" SortableDateTime
var u = String.Format("{0:u}", dt); // "2016-08-01 18:50:23Z"
UniversalSortableDateTime

Custom DateTime Formatting

There are following custom format specifiers:

y (year)
M (month)
d (day)
h (hour 12)
H (hour 24)
m (minute)
s (second)
f (second fraction)
F (second fraction, trailing zeroes are trimmed)
t (P.M or A.M)
z (time zone).

var year = var String.Format("{0:y yy yyy yyyy}", dt); // "16 16 2016 2016" year
month = var day = String.Format("{0:M MM MMM MMMM}", dt); // "8 08 Aug August" month
var hour = var String.Format("{0:d dd ddd dddd}", dt); // "1 01 Mon Monday" day
minute = var String.Format("{0:h hh H HH}", dt); // "6 06 18 18" hour 12/24
secound = var String.Format("{0:m mm}", dt); // "50 50" minute
fraction = var String.Format("{0:s ss}", dt); // "23 23" second
fraction2 = var String.Format("{0:f ff fff ffff}", dt); // "2 23 230 2300" sec.fraction
period = var zone = String.Format("{0:F FF FFF FFFF}", dt); // "2 23 23 23" without zeroes
String.Format("{0:t tt}", dt); // "P PM" A.M. or P.M.
String.Format("{0:z zz zzz}", dt); // "+0 +00 +00:00" time zone

You can use also date separator / (slash) and time sepatator : (colon).

INFOBYTE CAREER INSTITUTE 81


For code example

For more information MSDN.

Section 19.2: DateTime.AddDays(Double)


Add days into a dateTime object.

DateTime today = DateTime.Now;


DateTime answer = today.AddDays(36);
Console.WriteLine("Today: {0:dddd}", today);
Console.WriteLine("36 days from today: {0:dddd}", answer);

You also can subtract days passing a negative value:

DateTime today = DateTime.Now;


DateTime answer = today.AddDays(-3);
Console.WriteLine("Today: {0:dddd}", today);
Console.WriteLine("-3 days from today: {0:dddd}", answer);

Section 19.3: DateTime.AddHours(Double)


double[] hours = {.08333, .16667, .25, .33333, .5, .66667, 1, 2, 29, 30, 31, 90, 365};

DateTime dateValue = new DateTime(2009, 3, 1, 12, 0, 0);

foreach (double hour in hours)


Console.WriteLine("{0} + {1} hour(s) = {2}", dateValue, hour,
dateValue.AddHours(hour));

Section 19.4: DateTime.Parse(String)


// Converts the string representation of a date and time to its DateTime equivalent

var dateTime = DateTime.Parse("14:23 22 Jul 2016");

Console.WriteLine(dateTime.ToString());

Section 19.5: DateTime.TryParse(String, DateTime)


Converts the specified string representation of a date and time to its DateTime equivalent and returns a value that indicates
whether the conversion succeeded

string[] dateTimeStrings = new []{


"14:23 22 Jul 2016",
"99:23 2x Jul 2016",
"22/7/2016 14:23:00"
};

foreach(var dateTimeString in dateTimeStrings){

DateTime dateTime;

bool wasParsed = DateTime.TryParse(dateTimeString, out dateTime);

string result = dateTimeString +


(wasParsed

INFOBYTE CAREER INSTITUTE 82


$"was parsed to {dateTime}"
"can't be parsed to DateTime");

Console.WriteLine(result);

Section 19.6: DateTime.AddMilliseconds(Double)


string dateFormat = "MM/dd/yyyy hh:mm:ss.fffffff"; DateTime date1 = new
DateTime(2010, 9, 8, 16, 0, 0); Console.WriteLine("Original date: {0} ({1:N0}
ticks)\n",
date1.ToString(dateFormat), date1.Ticks);

DateTime date2 = date1.AddMilliseconds(1);


Console.WriteLine("Second date: {0} ({1:N0} ticks)",
date2.ToString(dateFormat), date2.Ticks);
Console.WriteLine("Difference between dates: {0} ({1:N0} ticks)\n", date2 - date1,
date2.Ticks - date1.Ticks);

DateTime date3 = date1.AddMilliseconds(1.5);


Console.WriteLine("Third date: {0} ({1:N0} ticks)", date3.ToString(dateFormat),
date3.Ticks);
Console.WriteLine("Difference between dates: {0} ({1:N0} ticks)", date3 - date1,
date3.Ticks - date1.Ticks);

Section 19.7: DateTime.Compare(DateTime t1, DateTime t2 )


DateTime date1 = new DateTime(2009, 8, 1, 0, 0, 0); DateTime date2
= new DateTime(2009, 8, 1, 12, 0, 0); int result =
DateTime.Compare(date1, date2); string relationship;

if (result < 0)
relationship = "is earlier than";
else if (result == 0)
relationship = "is the same time as";
else relationship = "is later than";

Console.WriteLine("{0} {1} {2}", date1, relationship, date2);

Section 19.8: DateTime.DaysInMonth(Int32, Int32)


const int July = 7;
const int Feb = 2;

int daysInJuly = System.DateTime.DaysInMonth(2001, July);


Console.WriteLine(daysInJuly);

daysInFeb gets 28 because the year 1998 was not a leap year. int daysInFeb =
System.DateTime.DaysInMonth(1998, Feb); Console.WriteLine(daysInFeb);

daysInFebLeap gets 29 because the year 1996 was a leap year. int
daysInFebLeap = System.DateTime.DaysInMonth(1996, Feb);
Console.WriteLine(daysInFebLeap);

INFOBYTE CAREER INSTITUTE 83


Section 19.9: DateTime.AddYears(Int32)
Add years on the dateTime object:

DateTime baseDate = new DateTime(2000, 2, 29);


Console.WriteLine("Base Date: {0:d}\n", baseDate);

Show dates of previous fifteen years. for (int ctr


= -1; ctr >= -15; ctr--)
Console.WriteLine("{0,2} year(s) ago:{1:d}",
Math.Abs(ctr), baseDate.AddYears(ctr));

Console.WriteLine();

Show dates of next fifteen years. for (int ctr


= 1; ctr <= 15; ctr++)
Console.WriteLine("{0,2} year(s) from now: {1:d}",
ctr, baseDate.AddYears(ctr));

Section 19.10: Pure functions warning when dealing


with DateTime
Wikipedia currently defines a pure function as follows:

The function always evaluates the same result value given the same argument value(s). The function result value
cannot depend on any hidden information or state that may change while program execution proceeds or between
different executions of the program, nor can it depend on any external input from I/O devices .
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of
mutable objects or output to I/O devices

As a developer you need to be aware of pure methods and you will stumble upon these a lot in many areas. One I have
seen that bites many junior developers is working with DateTime class methods. A lot of these are pure and if you are
unaware of these you can be in for a suprise. An example:

DateTime sample = new DateTime(2016, 12, 25);


sample.AddDays(1);
Console.WriteLine(sample.ToShortDateString());

Given the example above one may expect the result printed to console to be '26/12/2016' but in reality you end up with
the same date. This is because AddDays is a pure method and does not affect the original date. To get the expected
output you would have to modify the AddDays call to the following:

sample = sample.AddDays(1);

Section 19.11:
DateTime.TryParseExact(String, String, IFormatProvider, D
ateTimeStyles, DateTime)
Converts the specified string representation of a date and time to its DateTime equivalent using the specified
format, culture-specific format information, and style. The format of the string representation must match the
specified format exactly. The method returns a value that indicates whether the conversion succeeded.

For Example

CultureInfo enUS = new CultureInfo("en-US");

INFOBYTE CAREER INSTITUTE 84


string dateString;
System.DateTime dateValue;

Parse date with no style flags.

dateString = " 5/01/2009 8:30 AM";


if (DateTime.TryParseExact(dateString, "g", enUS, DateTimeStyles.None, out dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);
}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

// Allow a leading space in the date string.


if(DateTime.TryParseExact(dateString, "g", enUS, DateTimeStyles.AllowLeadingWhite, out dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind); else

{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

Use custom formats with M and MM.

dateString = "5/01/2009 09:00";


if(DateTime.TryParseExact(dateString, "M/dd/yyyy hh:mm", enUS, DateTimeStyles.None, out dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);
}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

// Allow a leading space in the date string.


if(DateTime.TryParseExact(dateString, "MM/dd/yyyy hh:mm", enUS, DateTimeStyles.None, out
dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);
}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

Parse a string with time zone information.

dateString = "05/01/2009 01:30:42 PM -05:00";


if (DateTime.TryParseExact(dateString, "MM/dd/yyyy hh:mm:ss tt zzz", enUS, DateTimeStyles.None, out
dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);
}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

INFOBYTE CAREER INSTITUTE 85


// Allow a leading space in the date string.
if (DateTime.TryParseExact(dateString, "MM/dd/yyyy hh:mm:ss tt zzz", enUS,
DateTimeStyles.AdjustToUniversal, out dateValue)) {

Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);


}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

Parse a string represengting UTC.

dateString = "2008-06-11T16:11:20.0904778Z";
if(DateTime.TryParseExact(dateString, "o", CultureInfo.InvariantCulture, DateTimeStyles.None, out
dateValue))
{
Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);
}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

if (DateTime.TryParseExact(dateString, "o", CultureInfo.InvariantCulture,


DateTimeStyles.RoundtripKind, out dateValue)) {

Console.WriteLine("Converted '{0}' to {1} ({2}).", dateString, dateValue, dateValue.Kind);


}
else
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}

Outputs

' 5/01/2009 8:30 AM' is not in an acceptable format.


Converted ' 5/01/2009 8:30 AM' to 5/1/2009 8:30:00 AM (Unspecified).
Converted '5/01/2009 09:00' to 5/1/2009 9:00:00 AM (Unspecified).
'5/01/2009 09:00' is not in an acceptable format.
Converted '05/01/2009 01:30:42 PM -05:00' to 5/1/2009 11:30:42 AM (Local).
Converted '05/01/2009 01:30:42 PM -05:00' to 5/1/2009 6:30:42 PM (Utc).
Converted '2008-06-11T16:11:20.0904778Z' to 6/11/2008 9:11:20 AM (Local).
Converted '2008-06-11T16:11:20.0904778Z' to 6/11/2008 4:11:20 PM (Utc).

Section 19.12: DateTime.Add(TimeSpan)


Calculate what day of the week is 36 days from this instant. System.DateTime
today = System.DateTime.Now; System.TimeSpan duration = new
System.TimeSpan(36, 0, 0, 0); System.DateTime answer = today.Add(duration);
System.Console.WriteLine("{0:dddd}", answer);

Section 19.13: Parse and TryParse with culture info


You might want to use it when parsing DateTimes from different cultures (languages), following example parses
Dutch date.

INFOBYTE CAREER INSTITUTE 86


DateTime dateResult;
var dutchDateString = "31 oktober 1999 04:20";
var dutchCulture = CultureInfo.CreateSpecificCulture("nl-NL");
DateTime.TryParse(dutchDateString, dutchCulture, styles, out dateResult); // output {31/10/1999
04:20:00}

Example of Parse:

DateTime.Parse(dutchDateString, dutchCulture)
// output {31/10/1999 04:20:00}

Section 19.14: DateTime as initializer in for-loop


This iterates through a range between two DateTimes
with the given iterator (any of the Add methods)

DateTime start = new DateTime(2016, 01, 01);


DateTime until = new DateTime(2016, 02, 01);

NOTICE: As the add methods return a new DateTime you have


to overwrite dt in the iterator like dt = dt.Add()
for (DateTime dt = start; dt < until; dt = dt.AddDays(1))
{
Console.WriteLine("Added {0} days. Resulting DateTime: {1}", (dt - start).Days,
dt.ToString());
}

Iterating on a TimeSpan works the same way.

Section 19.15:
DateTime.ParseExact(String, String, IFormatProvider)
Converts the specified string representation of a date and time to its DateTime equivalent using the specified format
and culture-specific format information. The format of the string representation must match the specified format
exactly.

Convert a specific format string to equivalent DateTime

Let's say we have a culture-specific DateTime string 08-07-2016 11:30:12 PM as MM-dd-yyyy hh:mm:ss tt format and we
want it to convert to equivalent DateTime object

string str = "08-07-2016 11:30:12 PM";


DateTime date = DateTime.ParseExact(str, "MM-dd-yyyy hh:mm:ss tt", CultureInfo.CurrentCulture);

Convert a date time string to equivalent DateTime object without any specific culture format

Let's say we have a DateTime string in dd-MM-yy hh:mm:ss tt format and we want it to convert to equivalent
DateTime object, without any specific culture information

string str = "17-06-16 11:30:12 PM";


DateTime date = DateTime.ParseExact(str, "dd-MM-yy hh:mm:ss tt", CultureInfo.InvariantCulture);

Convert a date time string to equivalent DateTime object without any specific culture format with different format

INFOBYTE CAREER INSTITUTE 87


Let's say we have a Date string , example like '23-12-2016' or '12/23/2016' and we want it to convert to equivalent
DateTime object, without any specific culture information

string date = '23-12-2016' or date = 12/23/2016';


string[] formats = new string[] {"dd-MM-yyyy","MM/dd/yyyy"}; // even can add more possible formats.

DateTime date = DateTime.ParseExact(date,formats,


CultureInfo.InvariantCulture,DateTimeStyles.None);

NOTE : System.Globalization needs to be added for CultureInfo Class

Section 19.16: DateTime ToString, ToShortDateString,


ToLongDateString and ToString formatted
using System;

public class Program


{
public static void Main()
{
var date = new DateTime(2016,12,31);

Console.WriteLine(date.ToString()); //Outputs: 12/31/2016 12:00:00 AM


Console.WriteLine(date.ToShortDateString()); //Outputs: 12/31/2016
Console.WriteLine(date.ToLongDateString()); //Outputs: Saturday, December 31, 2016
Console.WriteLine(date.ToString("dd/MM/yyyy")); //Outputs: 31/12/2016
}
}

Section 19.17: Current Date


To get the current date you use the DateTime.Today property. This returns a DateTime object with today's date.
When this is then converted .ToString() it is done so in your system's locality by default.

For example:

Console.WriteLine(DateTime.Today);

Writes today's date, in your local format to the console.

INFOBYTE CAREER INSTITUTE 88


Chapter 20: Arrays
Section 20.1: Declaring an array
An array can be declared and filled with the default value using square bracket ([]) initialization syntax. For
example, creating an array of 10 integers:

int[] arr = new int[10];

Indices in C# are zero-based. The indices of the array above will be 0-9. For example:

int[] arr = new int[3] {7,9,4};


Console.WriteLine(arr[0]); //outputs 7
Console.WriteLine(arr[1]); //outputs 9

Which means the system starts counting the element index from 0. Moreover, accesses to elements of arrays are done
in constant time. That means accessing to the first element of the array has the same cost (in time) of accessing the
second element, the third element and so on.

You may also declare a bare reference to an array without instantiating an array.

int[] arr = null; // OK, declares a null reference to an array.


int first = arr[0]; // Throws System.NullReferenceException because there is no actual array.

An array can also be created and initialized with custom values using collection initialization syntax:

int[] arr = new int[] { 24, 2, 13, 47, 45 };

The new int[] portion can be omitted when declaring an array variable. This is not a self-contained expression, so using
it as part of a different call does not work (for that, use the version with new):

int[] arr = { 24, 2, 13, 47, 45 }; // OK


int[] arr1;
arr1 = { 24, 2, 13, 47, 45 }; // Won't compile

Implicitly typed arrays

Alternatively, in combination with the var keyword, the specific type may be omitted so that the type of the array is
inferred:

// same as int[]
var arr = new [] { 1, 2, 3 };
// same as string[]
var arr = new [] { "one", "two", "three" };
// same as double[]
var arr = new [] { 1.0, 2.0, 3.0 };

Section 20.2: Initializing an array filled with a repeated non-


default value
As we know we can declare an array with default values:

int[] arr = new int[10];

INFOBYTE CAREER INSTITUTE 89


This will create an array of 10 integers with each element of the array having value 0 (the default value of type int).

To create an array initialized with a non-default value, we can use Enumerable.Repeat from the System.Linq
Namespace:

1. To create a bool array of size 10 filled with "true"

bool[] booleanArray = Enumerable.Repeat(true, 10).ToArray();

2. To create an int array of size 5 filled with "100"

int[] intArray = Enumerable.Repeat(100, 5).ToArray();

3. To create a string array of size 5 filled with "C#"

string[] strArray = Enumerable.Repeat("C#", 5).ToArray();

Section 20.3: Copying arrays


Copying a partial array with the static Array.Copy() method, beginning at index 0 in both, source and destination:

var sourceArray = new int[] { 11, 12, 3, 5, 2, 9, 28, 17 };


var destinationArray= new int[3];
Array.Copy(sourceArray, destinationArray, 3);

// destinationArray will have 11,12 and 3

Copying the whole array with the CopyTo() instance method, beginning at index 0 of the source and the specified index
in the destination:

var sourceArray = new int[] { 11, 12, 7 };


var destinationArray = new int[6];
sourceArray.CopyTo(destinationArray, 2);

// destinationArray will have 0, 0, 11, 12, 7 and 0

Clone is used to create a copy of an array object.

var sourceArray = new int[] { 11, 12, 7 };


var destinationArray = (int)sourceArray.Clone();

//destinationArray will be created and will have 11,12,17.

Both CopyTo and Clone perform shallow copy which means the contents contains references to the same object as the
elements in the original array.

Section 20.4: Comparing arrays for equality


LINQ provides a built-in function for checking the equality of two IEnumerables, and that function can be used on arrays.

The SequenceEqual function will return true if the arrays have the same length and the values in corresponding indices
are equal, and false otherwise.

INFOBYTE CAREER INSTITUTE 90


int[] arr1 = { 3, 5, 7 };
int[] arr2 = { 3, 5, 7 };
bool result = arr1.SequenceEqual(arr2);
Console.WriteLine("Arrays equal? {0}", result);

This will print:

Arrays equal? True

Section 20.5: Multi-dimensional arrays


Arrays can have more than one dimension. The following example creates a two-dimensional array of ten rows and ten
columns:

int[,] arr = new int[10, 10];

An array of three dimensions:

int[,,] arr = new int[10, 10, 10];

You can also initialize the array upon declaration:

int[,] arr = new int[4, 2] { {1, 1}, {2, 2}, {3, 3}, {4, 4} };

Access a member of the multi-dimensional array:


Console.Out.WriteLine(arr[3, 1]); // 4

Section 20.6: Getting and setting array values


int[] arr = new int[] { 0, 10, 20, 30};

// Get
Console.WriteLine(arr[2]); // 20

// Set
arr[2] = 100;

// Get the updated value


Console.WriteLine(arr[2]); // 100

Section 20.7: Iterate over an array


int[] arr = new int[] {1, 6, 3, 3, 9};

for (int i = 0; i < arr.Length; i++)


{
Console.WriteLine(arr[i]);
}

using foreach:

foreach (int element in arr)


{
Console.WriteLine(element);
}

INFOBYTE CAREER INSTITUTE 91


using unsafe access with pointers https://msdn.microsoft.com/en-ca/library/y31yhkeb.aspx

unsafe
{
int length = arr.Length;
fixed (int* p = arr)
{
int* pInt = p;
while (length-- > 0)
{
Console.WriteLine(*pInt);
pInt++;// move pointer to next element
}
}
}

Output:

1
6
3
3
9

Section 20.8: Creating an array of sequential numbers


LINQ provides a method that makes it easy to create a collection filled with sequential numbers. For example, you can
declare an array which contains the integers between 1 and 100.

The Enumerable.Range method allows us to create sequence of integer numbers from a specified start position and a
number of elements.

The method takes two arguments: the starting value and the number of elements to generate.

Enumerable.Range(int start, int count)

Note that count cannot be negative.

Usage:
int[] sequence = Enumerable.Range(1, 100).ToArray();

This will generate an array containing the numbers 1 through 100 ( [1, 2, 3, ..., 98, 99, 100]).

Because the Range method returns an IEnumerable<int>, we can use other LINQ methods on it:

int[] squares = Enumerable.Range(2, 10).Select(x => x * x).ToArray();

This will generate an array that contains 10 integer squares starting at 4: [4, 9, 16, ..., 100, 121].

Section 20.9: Jagged arrays


Jagged arrays are arrays that instead of primitive types, contain arrays (or other collections). It's like an array of
arrays - each array element contains another array.

INFOBYTE CAREER INSTITUTE 92


They are similar to multidimensional arrays, but have a slight difference - as multidimensional arrays are limited to a
fixed number of rows and columns, with jagged arrays, every row can have a different number of columns.

Declaring a jagged array

For example, declaring a jagged array with 8 columns:

int[][] a = new int[8][];

The second [] is initialized without a number. To initialize the sub arrays, you would need to do that separately:

for (int i = 0; i < a.length; i++)


{
a[i] = new int[10];
}

Getting/Setting values

Now, getting one of the subarrays is easy. Let's print all the numbers of the 3rd column of a:

for (int i = 0; i < a[2].length; i++)


{
Console.WriteLine(a[2][i]);
}

Getting a specific value:

a[<row_number>][<column_number>]

Setting a specific value:

a[<row_number>][<column_number>] = <value>

Remember: It's always recommended to use jagged arrays (arrays of arrays) rather than multidimensional arrays
(matrixes). It's faster and safer to use.

Note on the order of the brackets

Consider a three-dimensional array of five-dimensional arrays of one-dimensional arrays of int. This is written in
C# as:

int[,,][,,,,][] arr = new int[8, 10, 12][,,,,][];

In the CLR type system, the convention for the ordering of the brackets is reversed, so with the above arr instance we
have:

arr.GetType().ToString() == "System.Int32[][,,,,][,,]"

and likewise:

typeof(int[,,][,,,,][]).ToString() == "System.Int32[][,,,,][,,]"

INFOBYTE CAREER INSTITUTE 93


Section 20.10: Array covariance
string[] strings = new[] {"foo", "bar"};
object[] objects = strings; // implicit conversion from string[] to object[]

This conversion is not type-safe. The following code will raise a runtime exception:

string[] strings = new[] {"Foo"};


object[] objects = strings;

objects[0] = new object(); // runtime exception, object is not string


string str = strings[0]; // would have been bad if above assignment had succeeded

Section 20.11: Arrays as IEnumerable<> instances


All arrays implement the non-generic IList interface (and hence non-generic ICollection and IEnumerable base interfaces).

More importantly, one-dimensional arrays implement the IList<> and IReadOnlyList<> generic interfaces (and their base
interfaces) for the type of data that they contain. This means that they can be treated as generic enumerable types and
passed in to a variety of methods without needing to first convert them to a non-array form.

int[] arr1 = { 3, 5, 7 };
IEnumerable<int> enumerableIntegers = arr1; //Allowed because arrays implement IEnumerable<T> List<int> listOfIntegers
= new List<int>();
listOfIntegers.AddRange(arr1); //You can pass in a reference to an array to populate a List.

After running this code, the list listOfIntegers will contain a List<int> containing the values 3, 5, and 7.

The IEnumerable<> support means arrays can be queried with LINQ, for example arr1.Select(i => 10 * i).

Section 20.12: Checking if one array contains another array


public static class ArrayHelpers
{
public static bool Contains<T>(this T[] array, T[] candidate)
{
if (IsEmptyLocate(array, candidate))
return false;

if (candidate.Length > array.Length)


return false;

for (int a = 0; a <= array.Length - candidate.Length; a++)


{
if (array[a].Equals(candidate[0]))
{
int i = 0;
for (; i < candidate.Length; i++)
{
if (false == array[a + i].Equals(candidate[i]))
break;
}
if (i == candidate.Length)
return true;
}
}

INFOBYTE CAREER INSTITUTE 94


return false;
}

static bool IsEmptyLocate<T>(T[] array, T[] candidate)


{
return array == null
candidate == null
array.Length == 0
candidate.Length == 0
candidate.Length > array.Length;
}
}

/// Sample

byte[] EndOfStream = Encoding.ASCII.GetBytes("---3141592---");


byte[] FakeReceivedFromStream = Encoding.ASCII.GetBytes("Hello, world!!!---3141592---"); if
(FakeReceivedFromStream.Contains(EndOfStream)) {

Console.WriteLine("Message received");
}

INFOBYTE CAREER INSTITUTE 95


Chapter 21: O(n) Algorithm for circular
rotation of an array
In my path to studying programming there have been simple, but interesting problems to solve as exercises. One of those
problems was to rotate an array(or another collection) by a certain value. Here I will share with you a simple formula to do
it.

Section 21.1: Example of a generic method that rotates an


array by a given shift
I would like to point out that we rotate left when the shifting value is negative and we rotate right when the value is
positive.

public static void Main()


{
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int shiftCount = 1;
Rotate(ref array, shiftCount);
Console.WriteLine(string.Join(", ", array));
// Output: [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]

array = new []{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };


shiftCount = 15;
Rotate(ref array, shiftCount);
Console.WriteLine(string.Join(", ", array));
// Output: [6, 7, 8, 9, 10, 1, 2, 3, 4, 5]

array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
shiftCount = -1;
Rotate(ref array, shiftCount);
Console.WriteLine(string.Join(", ", array));
// Output: [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]

array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
shiftCount = -35;
Rotate(ref array, shiftCount);
Console.WriteLine(string.Join(", ", array));
// Output: [6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
}

private static void Rotate<T>(ref T[] array, int shiftCount)


{
T[] backupArray= new T[array.Length];

for (int index = 0; index < array.Length; index++)


{
backupArray[(index + array.Length + shiftCount % array.Length) % array.Length] = array[index];

array = backupArray;
}

The thing that is important in this code is the formula with which we find the new index value after the rotation.

(index + array.Length + shiftCount % array.Length) % array.Length

INFOBYTE CAREER INSTITUTE 96


Here is a little more information about it:

(shiftCount % array.Length) -> we normalize the shifting value to be in the length of the array (since in an array with
length 10, shifting 1 or 11 is the same thing, the same goes for -1 and -11).

array.Length + (shiftCount % array.Length) -> this is done due to left rotations to make sure we do not go into a
negative index, but rotate it to the end of the array. Without it for an array with length 10 for index 0 and a rotation -1 we
would go into a negative number (-1) and not get the real rotation index value, which is 9. (10 + (-1 % 10) = 9)

index + array.Length + (shiftCount % array.Length) -> not much to say here as we apply the rotation to the index to
get the new index. (0 + 10 + (-1 % 10) = 9)

index + array.Length + (shiftCount % array.Length) % array.Length -> the second normalization is making sure that
the new index value does not go outside of the array, but rotates the value in the beginning of the array. It is for right
rotations, since in an array with length 10 without it for index 9 and a rotation 1 we would go into index 10, which is
outside of the array, and not get the real rotation index value is 0. ((9 + 10 + (1 % 10)) % 10 = 0)

INFOBYTE CAREER INSTITUTE 97


Chapter 22: Enum
An enum can derive from any of the following types: byte, sbyte, short, ushort, int, uint, long, ulong. The default is int,
and can be changed by specifying the type in the enum definition:

public enum Weekday : byte { Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5 }

This is useful when P/Invoking to native code, mapping to data sources, and similar circumstances. In general, the
default int should be used, because most developers expect an enum to be an int.

Section 22.1: Enum basics


From MSDN:

An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of
named integral constants that may be assigned to a variable.

Essentially, an enum is a type that only allows a set of finite options, and each option corresponds to a number. By
default, those numbers are increasing in the order the values are declared, starting from zero. For example, one could
declare an enum for the days of the week:

public enum Day


{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}

That enum could be used like this:

Define variables with values corresponding to specific days Day


myFavoriteDay = Day.Friday;
Day myLeastFavoriteDay = Day.Monday;

Get the int that corresponds to myFavoriteDay


Friday is number 4
int myFavoriteDayIndex = (int)myFavoriteDay;

Get the day that represents number 5 Day


dayFive = (Day)5;

By default the underlying type of each element in the enum is int, but byte, sbyte, short, ushort, uint, long and ulong can be
used as well. If you use a type other than int, you must specify the type using a colon after the enum name:

public enum Day : byte


{
// same as before
}

INFOBYTE CAREER INSTITUTE 98


The numbers after the name are now bytes instead of integers. You could get the underlying type of the enum as
follows:

Enum.GetUnderlyingType(typeof(Days)));

Output:

System.Byte

Demo: .NET fiddle

Section 22.2: Enum as flags


The FlagsAttribute can be applied to an enum changing the behaviour of the ToString() to match the nature of the enum:

[Flags]
enum MyEnum
{
//None = 0, can be used but not combined in bitwise operations
FlagA = 1,
FlagB = 2,
FlagC = 4,
FlagD = 8
//you must use powers of two or combinations of powers of two //for bitwise
operations to work
}

var twoFlags = MyEnum.FlagA | MyEnum.FlagB;

This will enumerate all the flags in the variable: "FlagA, FlagB".
Console.WriteLine(twoFlags);

Because FlagsAttribute relies on the enumeration constants to be powers of two (or their combinations) and enum values
are ultimately numeric values, you are limited by the size of the underlying numeric type. The largest available numeric
type that you can use is UInt64, which allows you to specify 64 distinct (non-combined) flag enum constants. The enum
keyword defaults to the underlying type int, which is Int32. The compiler will allow the declaration of values wider than 32
bit. Those will wrap around without a warning and result in two or more enum members of the same value. Therefore, if
an enum is meant to accomodate a bitset of more than 32 flags, you need to specify a bigger type explicitely:

public enum BigEnum : ulong


{
BigValue = 1 << 63
}

Although flags are often only a single bit, they can be combined into named "sets" for easier use.

[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,

Default = Option1 | Option3,

INFOBYTE CAREER INSTITUTE 99


All = Option1 | Option2 | Option3,
}

To avoid spelling out the decimal values of powers of two, the left-shift operator (<<) can also be used to declare the
same enum

[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2,

Default = Option1 | Option3,


All = Option1 | Option2 | Option3,
}

Starting with C# 7.0, binary literals can be used too.

To check if the value of enum variable has a certain flag set, the HasFlag method can be used. Let's say we have

[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Three = 4
}

And a value

var value = MyEnum.One | MyEnum.Two;

With HasFlag we can check if any of the flags is set

if(value.HasFlag(MyEnum.One))
Console.WriteLine("Enum has One");

if(value.HasFlag(MyEnum.Two))
Console.WriteLine("Enum has Two");

if(value.HasFlag(MyEnum.Three))
Console.WriteLine("Enum has Three");

Also we can iterate through all values of enum to get all flags that are set

var type = typeof(MyEnum);


var names = Enum.GetNames(type);

foreach (var name in names)


{
var item = (MyEnum)Enum.Parse(type, name);

if (value.HasFlag(item))
Console.WriteLine("Enum has " + name);
}

INFOBYTE CAREER INSTITUTE 100


Or

foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))


{
if(value.HasFlag(flagToCheck))
{
Console.WriteLine("Enum has " + flagToCheck);
}
}

All three examples will print:

Enum has One


Enum has Two

Section 22.3: Using << notation for flags


The left-shift operator (<<) can be used in flag enum declarations to ensure that each flag has exactly one 1 in
binary representation, as flags should.

This also helps to improve readability of large enums with plenty of flags in them.

[Flags]
public enum MyEnum
{
None = 0,
Flag1 =1<<0,
Flag2 =1<<1,
Flag3 =1<<2,
Flag4 = 1 << 3,
Flag5 = 1 << 4,
...
Flag31 = 1 << 30
}

It is obvious now that MyEnum contains proper flags only and not any messy stuff like Flag30 = 1073741822 (or
111111111111111111111111111110 in binary) which is inappropriate.

Section 22.4: Test flags-style enum values with bitwise logic


A flags-style enum value needs to be tested with bitwise logic because it may not match any single value.

[Flags]
enum FlagsEnum
{
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option2And3 = Option2 | Option3;

Default = Option1 | Option3,


}

The Default value is actually a combination of two others merged with a bitwise OR. Therefore to test for the
presence of a flag we need to use a bitwise AND.

var value = FlagsEnum.Default;

INFOBYTE CAREER INSTITUTE 101


bool isOption2And3Set = (value & FlagsEnum.Option2And3) == FlagsEnum.Option2And3;

Assert.True(isOption2And3Set);

Section 22.5: Add and remove values from flagged enum


This code is to add and remove a value from a flagged enum-instance:

[Flags]
public enum MyEnum
{
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2
}

var value = MyEnum.Flag1;

// set additional value


value |= MyEnum.Flag2; //value is now Flag1, Flag2
value |= MyEnum.Flag3; //value is now Flag1, Flag2, Flag3

// remove flag
value &= ~MyEnum.Flag2; //value is now Flag1, Flag3

Section 22.6: Enum to string and back


public enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}

// Enum to string
string thursday = DayOfWeek.Thursday.ToString(); // "Thursday"

string seventhDay = Enum.GetName(typeof(DayOfWeek), 6); // "Saturday"

string monday = Enum.GetName(typeof(DayOfWeek), DayOfWeek.Monday); // "Monday"

String to enum (.NET 4.0+ only - see below for alternative syntax for earlier .NET versions) DayOfWeek tuesday;

Enum.TryParse("Tuesday", out tuesday); // DayOfWeek.Tuesday

DayOfWeek sunday;
bool matchFound1 = Enum.TryParse("SUNDAY", out sunday); // Returns false (case-sensitive match)

DayOfWeek wednesday;
bool matchFound2 = Enum.TryParse("WEDNESDAY", true, out wednesday); // Returns true;
DayOfWeek.Wednesday (case-insensitive match)

// String to enum (all .NET versions)

INFOBYTE CAREER INSTITUTE 102


DayOfWeek friday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Friday"); // DayOfWeek.Friday

DayOfWeek caturday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Caturady"); // Thows


ArgumentException

// All names of an enum type as strings


string[] weekdays = Enum.GetNames(typeof(DayOfWeek));

Section 22.7: Enums can have unexpected values


Since an enum can be cast to and from its underlying integral type, the value may fall outside the range of values
given in the definition of the enum type.

Although the below enum type DaysOfWeek only has 7 defined values, it can still hold any int value.

public enum DaysOfWeek


{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7
}

DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(d); // prints 31

DaysOFWeek s = DaysOfWeek.Sunday;
s++; // No error

There is currently no way to define an enum which does not have this behavior.

However, undefined enum values can be detected by using the method Enum.IsDefined. For example,

DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(Enum.IsDefined(typeof(DaysOfWeek),d)); // prints False

Section 22.8: Default value for enum == ZERO


The default value for an enum is zero. If an enum does not define an item with a value of zero, its default value will
be zero.

public class Program


{
enum EnumExample
{
one = 1,
two = 2
}

public void Main()


{
var e = default(EnumExample);

if (e == EnumExample.one)
Console.WriteLine("defaults to one");

INFOBYTE CAREER INSTITUTE 103


else
Console.WriteLine("Unknown");
}
}

Example: https://dotnetfiddle.net/l5Rwie

Section 22.9: Adding additional description information to an


enum value
In some cases you might want to add an additional description to an enum value, for instance when the enum value
itself is less readable than what you might want to display to the user. In such cases you can use the
System.ComponentModel.DescriptionAttribute class.

For example:

public enum PossibleResults


{
[Description("Success")]
OK=1,
[Description("File not found")]
FileNotFound = 2,
[Description("Access denied")]
AccessDenied = 3
}

Now, if you would like to return the description of a specific enum value you can do the following:

public static string GetDescriptionAttribute(PossibleResults result)


{
return
((DescriptionAttribute)Attribute.GetCustomAttribute((result.GetType().GetField(result.ToString())),
typeof(DescriptionAttribute))).Description;
}

static void Main(string[] args)


{
PossibleResults result = PossibleResults.FileNotFound;
Console.WriteLine(result); // Prints "FileNotFound"
Console.WriteLine(GetDescriptionAttribute(result)); // Prints "File not found"
}

This can also be easily transformed to an extension method for all enums:

static class EnumExtensions


{
public static string GetDescription(this Enum enumValue)
{
return
((DescriptionAttribute)Attribute.GetCustomAttribute((enumValue.GetType().GetField(enumValue.ToStrin
g())), typeof(DescriptionAttribute))).Description;
}
}

And then easily used like this: Console.WriteLine(result.GetDescription());

INFOBYTE CAREER INSTITUTE 104


Section 22.10: Get all the members values of an enum
enum MyEnum
{
One,
Two,
Three
}

foreach(MyEnum e in Enum.GetValues(typeof(MyEnum)))
Console.WriteLine(e);

This will print:

One
Two
Three

Section 22.11: Bitwise Manipulation using enums


The FlagsAttribute should be used whenever the enumerable represents a collection of flags, rather than a single
value. The numeric value assigned to each enum value helps when manipulating enums using bitwise operators.

Example 1 : With [Flags]

[Flags]
enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}

var color = Colors.Red | Colors.Blue;


Console.WriteLine(color.ToString());

prints Red,Blue

Example 2 : Without [Flags]

enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}
var color = Colors.Red | Colors.Blue;
Console.WriteLine(color.ToString());

prints 3

INFOBYTE CAREER INSTITUTE 105


Chapter 23: Tuples
Section 23.1: Accessing tuple elements
To access tuple elements use Item1-Item8 properties. Only the properties with index number less or equal to tuple size
are going to be available (i.e. one cannot access Item3 property in Tuple<T1,T2>).

var tuple = new Tuple<string, int, bool, MyClass>("foo", 123, true, new MyClass());
var item1 = tuple.Item1; // "foo"
var item2 = tuple.Item2; // 123
var item3 = tuple.Item3; // true
var item4 = tuple.Item4; // new My Class()

Section 23.2: Creating tuples


Tuples are created using generic types Tuple<T1>-Tuple<T1,T2,T3,T4,T5,T6,T7,T8>. Each of the types represents a tuple
containing 1 to 8 elements. Elements can be of different types.

// tuple with 4 elements


var tuple = new Tuple<string, int, bool, MyClass>("foo", 123, true, new MyClass());

Tuples can also be created using static Tuple.Create methods. In this case, the types of the elements are inferred by the
C# Compiler.

// tuple with 4 elements


var tuple = Tuple.Create("foo", 123, true, new MyClass()); Version ≥ 7.0

Since C# 7.0, Tuples can be easily created using ValueTuple.

var tuple = ("foo", 123, true, new MyClass());

Elements can be named for easier decomposition.

(int number, bool flag, MyClass instance) tuple = (123, true, new MyClass());

Section 23.3: Comparing and sorting Tuples


Tuples can be compared based on their elements.

As an example, an enumerable whose elements are of type Tuple can be sorted based on comparisons operators
defined on a specified element:

List<Tuple<int, string>> list = new List<Tuple<int, string>>(); list.Add(new Tuple<int,


string>(2, "foo")); list.Add(new Tuple<int, string>(1, "bar"));

list.Add(new Tuple<int, string>(3, "qux"));

list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); //sort based on the string element

foreach (var element in list) {


Console.WriteLine(element);
}

// Output:

INFOBYTE CAREER INSTITUTE 106


(1, bar)
(2, foo)
(3, qux)

Or to reverse the sort use:

list.Sort((a, b) => b.Item2.CompareTo(a.Item2));

Section 23.4: Return multiple values from a method


Tuples can be used to return multiple values from a method without using out parameters. In the following
example AddMultiply is used to return two values (sum, product).

void Write()
{
var result = AddMultiply(25, 28);
Console.WriteLine(result.Item1);
Console.WriteLine(result.Item2);
}

Tuple<int, int> AddMultiply(int a, int b)


{
return new Tuple<int, int>(a + b, a * b);
}

Output:

53
700

Now C# 7.0 offers an alternative way to return multiple values from methods using value tuples More info about
ValueTuple struct.

INFOBYTE CAREER INSTITUTE 107


Chapter 24: Guid
GUID (or UUID) is an acronym for 'Globally Unique Identifier' (or 'Universally Unique Identifier'). It is a 128-bit
integer number used to identify resources.

Section 24.1: Getting the string representation of a Guid


A string representation of a Guid can be obtained by using the built in ToString method

string myGuidString = myGuid.ToString();

Depending on your needs you can also format the Guid, by adding a format type argument to the ToString call.

var guid = new Guid("7febf16f-651b-43b0-a5e3-0da8da49e90d");

// None "7febf16f651b43b0a5e30da8da49e90d"
Console.WriteLine(guid.ToString("N"));

// Hyphens "7febf16f-651b-43b0-a5e3-0da8da49e90d"
Console.WriteLine(guid.ToString("D"));

// Braces "{7febf16f-651b-43b0-a5e3-0da8da49e90d}"
Console.WriteLine(guid.ToString("B"));

// Parentheses "(7febf16f-651b-43b0-a5e3-0da8da49e90d)"
Console.WriteLine(guid.ToString("P"));

// Hex "{0x7febf16f,0x651b,0x43b0{0xa5,0xe3,0x0d,0xa8,0xda,0x49,0xe9,0x0d}}"
Console.WriteLine(guid.ToString("X"));

Section 24.2: Creating a Guid


These are the most common ways to create an instance of Guid:

Creating an empty guid (00000000-0000-0000-0000-000000000000):

Guid g = Guid.Empty;
Guid g2 = new Guid();

Creating a new (pseudorandom) Guid:

Guid g = Guid.NewGuid();

Creating Guids with a specific value:

Guid g = new Guid("0b214de7-8958-4956-8eed-28f9ba2c47c6");


Guid g2 = new Guid("0b214de7895849568eed28f9ba2c47c6");
Guid g3 = Guid.Parse("0b214de7-8958-4956-8eed-28f9ba2c47c6");

Section 24.3: Declaring a nullable GUID


Like other value types, GUID also has a nullable type which can take null value.

Declaration :

Guid? myGuidVar = null;

INFOBYTE CAREER INSTITUTE 108


This is particularly useful when retrieving data from the data base when there is a possibility that value from a table is
NULL.

INFOBYTE CAREER INSTITUTE 109


Chapter 25: BigInteger
Section 25.1: Calculate the First 1,000-Digit Fibonacci Number
Include using System.Numerics and add a reference to System.Numerics to the project.

using System;
using System.Numerics;

namespace Euler_25
{
class Program
{
static void Main(string[] args)
{
BigInteger l1 = 1;
BigInteger l2 = 1;
BigInteger current = l1 + l2;
while (current.ToString().Length < 1000)
{
l2 = l1;
l1 = current;
current = l1 + l2;
}
Console.WriteLine(current);
}
}
}

This simple algorithm iterates through Fibonacci numbers until it reaches one at least 1000 decimal digits in length, then
prints it out. This value is significantly larger than even a ulong could hold.

Theoretically, the only limit on the BigInteger class is the amount of RAM your application can consume.

Note: BigInteger is only available in .NET 4.0 and higher.

INFOBYTE CAREER INSTITUTE 110


Chapter 26: Collection Initializers
Section 26.1: Collection initializers
Initialize a collection type with values:

var stringList = new List<string>


{
"foo",
"bar",
};

Collection initializers are syntactic sugar for Add() calls. Above code is equivalent to:

var temp = new List<string>();


temp.Add("foo");
temp.Add("bar");
var stringList = temp;

Note that the intialization is done atomically using a temporary variable, to avoid race conditions.

For types that offer multiple parameters in their Add() method, enclose the comma-separated arguments in curly braces:

var numberDictionary = new Dictionary<int, string>


{
{ 1, "One" }, { 2,
"Two" },
};

This is equivalent to:

var temp = new Dictionary<int, string>();


temp.Add(1, "One");
temp.Add(2, "Two");
var numberDictionarynumberDictionary = temp;

Section 26.2: C# 6 Index Initializers


Starting with C# 6, collections with indexers can be initialized by specifying the index to assign in square brackets,
followed by an equals sign, followed by the value to assign.

Dictionary Initialization

An example of this syntax using a Dictionary:

var dict = new Dictionary<string, int>


{
["key1"] = 1,
["key2"] = 50
};

This is equivalent to:

var dict = new Dictionary<string, int>();

INFOBYTE CAREER INSTITUTE 111


dict["key1"] = 1;
dict["key2"] = 50

The collection initializer syntax to do this before C# 6 was:

var dict = new Dictionary<string, int>


{
{ "key1", 1 }, {
"key2", 50 }
};

Which would correspond to:

var dict = new Dictionary<string, int>();


dict.Add("key1", 1);
dict.Add("key2", 50);

So there is a significant difference in functionality, as the new syntax uses the indexer of the initialized object to
assign values instead of using its Add() method. This means the new syntax only requires a publicly available
indexer, and works for any object that has one.

public class IndexableClass


{
public int this[int index]
{
set
{
Console.WriteLine("{0} was assigned to index {1}", value, index);
}
}
}

var foo = new IndexableClass


{
[0] = 10,
[1] = 20
}

This would output:

10 was assigned to index 0


20 was assigned to index 1

Section 26.3: Collection initializers in custom classes


To make a class support collection initializers, it must implement IEnumerable interface and have at least one Add
method. Since C# 6, any collection implementing IEnumerable can be extended with custom Add methods using
extension methods.

class Program
{
static void Main()
{
var col = new MyCollection {
"foo",
{ "bar", 3 },

INFOBYTE CAREER INSTITUTE 112


"baz",
123.45d,
};
}
}

class MyCollection : IEnumerable


{
private IList list = new ArrayList();

public void Add(string item)


{
list.Add(item)
}

public void Add(string item, int count)


{
for(int i=0;i< count;i++) {
list.Add(item);
}
}

public IEnumerator GetEnumerator()


{
return list.GetEnumerator();
}
}

static class MyCollectionExtensions


{
public static void Add(this MyCollection @this, double value) =>
@this.Add(value.ToString());
}

Section 26.4: Using collection initializer inside object initializer


public class Tag
{
public IList<string> Synonyms { get; set; }
}

Synonyms is a collection-type property. When the Tag object is created using object initializer syntax, Synonyms can also
be initialized with collection initializer syntax:

Tag t = new Tag


{
Synonyms = new List<string> {"c#", "c-sharp"}
};

The collection property can be readonly and still support collection initializer syntax. Consider this modified
example (Synonyms property now has a private setter):

public class Tag


{
public Tag()
{
Synonyms = new List<string>();
}

INFOBYTE CAREER INSTITUTE 113


public IList<string> Synonyms { get; private set; }
}

A new Tag object can be created like this:

Tag t = new Tag


{
Synonyms = {"c#", "c-sharp"}
};

This works because collection initializers are just syntatic sugar over calls to Add(). There's no new list being created here,
the compiler is just generating calls to Add() on the exiting object.

Section 26.5: Collection Initializers with Parameter Arrays


You can mix normal parameters and parameter arrays:

public class LotteryTicket : IEnumerable{


public int[] LuckyNumbers;
public string UserName;

public void Add(string userName, params int[] luckyNumbers){ UserName =


userName;
Lottery = luckyNumbers;
}
}

This syntax is now possible:

var Tickets = new List<LotteryTicket>{


{"Mr Cool" , 35663, 35732, 12312, 75685},
{"Bruce" , 26874, 66677, 24546, 36483, 46768, 24632, 24527},
{"John Cena", 25446, 83356, 65536, 23783, 24567, 89337}
}

INFOBYTE CAREER INSTITUTE 114


Chapter 27: An overview of C# collections
Section 27.1: HashSet<T>
This is a collection of unique items, with O(1) lookup.

HashSet<int> validStoryPointValues = new HashSet<int>() { 1, 2, 3, 5, 8, 13, 21 }; bool containsEight =


validStoryPointValues.Contains(8); // O(1)

By way of comparison, doing a Contains on a List yields poorer performance:

List<int> validStoryPointValues = new List<int>() { 1, 2, 3, 5, 8, 13, 21 }; bool containsEight =


validStoryPointValues.Contains(8); // O(n)

HashSet.Contains uses a hash table, so that lookups are extremely fast, regardless of the number of items in the
collection.

Section 27.2: Dictionary<TKey, TValue>


Dictionary<TKey, TValue> is a map. For a given key there can be one value in the dictionary.

using System.Collections.Generic;

var people = new Dictionary<string, int>


{
{ "John", 30 }, {"Mary", 35}, {"Jack", 40}
};

// Reading data
Console.WriteLine(people["John"]); // 30
Console.WriteLine(people["George"]); // throws KeyNotFoundException

int age;
if (people.TryGetValue("Mary", out age))
{
Console.WriteLine(age); // 35
}

// Adding and changing data


people["John"] = 40; // Overwriting values this way is ok
people.Add("John", 40); // Throws ArgumentException since "John" already exists

// Iterating through contents


foreach(KeyValuePair<string, int> person in people)
{
Console.WriteLine("Name={0}, Age={1}", person.Key, person.Value);
}

foreach(string name in people.Keys)


{
Console.WriteLine("Name={0}", name);
}

foreach(int age in people.Values)


{
Console.WriteLine("Age={0}", age);
}

INFOBYTE CAREER INSTITUTE 115


Duplicate key when using collection initialization
var people = new Dictionary<string, int>
{
{ "John", 30 }, {"Mary", 35}, {"Jack", 40}, {"Jack", 40} }; // throws
ArgumentException since "Jack" already exists

Section 27.3: SortedSet<T>


// create an empty set
var mySet = new SortedSet<int>();

add something
note that we add 2 before we add 1
mySet.Add(2);
mySet.Add(1);

enumerate through the set


foreach(var item in mySet)
{
Console.WriteLine(item);
}

output:
1
2

Section 27.4: T[ ] (Array of T)


// create an array with 2 elements
var myArray = new [] { "one", "two" };

enumerate through the array


foreach(var item in myArray)
{
Console.WriteLine(item);
}

output:
one
two

exchange the element on the first position


note that all collections start with the index 0 myArray[0] =
"something else";

enumerate through the array again


foreach(var item in myArray)
{
Console.WriteLine(item);
}

output:
something else
two

INFOBYTE CAREER INSTITUTE 116


Section 27.5: List<T>
List<T> is a list of a given type. Items can be added, inserted, removed and addressed by index.

using System.Collections.Generic;

var list = new List<int>() { 1, 2, 3, 4, 5 };


list.Add(6);
Console.WriteLine(list.Count); // 6
list.RemoveAt(3);
Console.WriteLine(list.Count); // 5
Console.WriteLine(list[3]); // 5

List<T> can be thought of as an array that you can resize. Enumerating over the collection in order is quick, as is
access to individual elements via their index. To access elements based on some aspect of their value, or some other
key, a Dictionary<T> will provide faster lookup.

Section 27.6: Stack<T>


Initialize a stack object of integers var stack =
new Stack<int>();

add some data


stack.Push(3);
stack.Push(5);
stack.Push(8);

elements are stored with "first in, last out" order.


stack from top to bottom is: 8, 5, 3

We can use peek to see the top element of the stack.


Console.WriteLine(stack.Peek()); // prints 8

Pop removes the top element of the stack and returns it.
Console.WriteLine(stack.Pop()); // prints 8 Console.WriteLine(stack.Pop()); //
prints 5 Console.WriteLine(stack.Pop()); // prints 3

Section 27.7: LinkedList<T>


initialize a LinkedList of integers
LinkedList list = new LinkedList<int>();

add some numbers to our list.


list.AddLast(3);
list.AddLast(5);
list.AddLast(8);

// the list currently is 3, 5, 8

list.AddFirst(2);
// the list now is 2, 3, 5, 8

list.RemoveFirst();
// the list is now 3, 5, 8

list.RemoveLast();
// the list is now 3, 5

INFOBYTE CAREER INSTITUTE 117


Note that LinkedList<T> represents the doubly linked list. So, it's simply collection of nodes and each node
contains an element of type T. Each node is linked to the preceding node and the following node.

Section 27.8: Queue


ᜀ Ā ᜀ Ā ᜀ Ā ᜀ Ā ᜀ Ā ᜀ
nitalize a new queue of integers var queue =
new Queue<int>();

ᜀ Ā ᜀ Ā ᜀ Ā ᜀ Ā ᜀ Ā ᜀ
dd some data
queue.Enqueue(6);
queue.Enqueue(4);
queue.Enqueue(9);

Elements in a queue are stored in "first in, first out" order.


The queue from first to last is: 6, 4, 9

View the next element in the queue, without removing it.


Console.WriteLine(queue.Peek()); // prints 6

Removes the first element in the queue, and returns it.


Console.WriteLine(queue.Dequeue()); // prints 6
Console.WriteLine(queue.Dequeue()); // prints 4
Console.WriteLine(queue.Dequeue()); // prints 9

Thread safe heads up! Use ConcurrentQueue in multi-thread environments.


INFOBYTE CAREER INSTITUTE 118
Chapter 28: Looping
Section 28.1: For Loop
A For Loop is great for doing things a certain amount of time. It's like a While Loop but the increment is included with
the condition.

A For Loop is set up like this:

for (Initialization; Condition; Increment)


{
// Code
}

Initialization - Makes a new local variable that can only be used in the loop.
Condition - The loop only runs when the condition is true.
Increment - How the variable changes every time the loop runs.

An example:

for (int i = 0; i < 5; i++)


{
Console.WriteLine(i);
}

Output:

0
1
2
3
4

You can also leave out spaces in the For Loop, but you have to have all semicolons for it to function.

int input = Console.ReadLine();

for ( ; input < 10; input + 2)


{
Console.WriteLine(input);
}

Output for 3:

3
5
7
9
11

INFOBYTE CAREER INSTITUTE 119


Section 28.2: Do - While Loop
It is similar to a while loop, except that it tests the condition at the end of the loop body. The Do - While loop
executes the loop once irrespective of whether the condition is true or not.

int[] numbers = new int[] { 6, 7, 8, 10 };

Sum values from the array until we get a total that's greater than 10,
or until we run out of values.
int sum = 0;
int i = 0;
do
{
sum += numbers[i];
i++;
} while (sum <= 10 && i < numbers.Length);

System.Console.WriteLine(sum); // 13

Section 28.3: Foreach Loop


foreach will iterate over any object of a class that implements IEnumerable (take note that IEnumerable<T> inherits from it).
Such objects include some built-in ones, but not limit to: List<T>, T[] (arrays of any type), Dictionary<TKey, TSource>, as
well as interfaces like IQueryable and ICollection, etc.

syntax

foreach(ItemType itemVariable in enumerableObject)


statement;

remarks

The type ItemType does not need to match the precise type of the items, it just needs to be assignable from the
type of the items
Instead of ItemType, alternatively var can be used which will infer the items type from the enumerableObject by
inspecting the generic argument of the IEnumerable implementation
The statement can be a block, a single statement or even an empty statement ( ;)
If enumerableObject is not implementing IEnumerable, the code will not compile
During each iteration the current item is cast to ItemType (even if this is not specified but compiler-inferred via
var) and if the item cannot be cast an InvalidCastException will be thrown.

Consider this example:

var list = new List<string>();


list.Add("Ion");
list.Add("Andrei");
foreach(var name in list)
{
Console.WriteLine("Hello " + name);
}

is equivalent to:

var list = new List<string>();


list.Add("Ion");
list.Add("Andrei");

INFOBYTE CAREER INSTITUTE 120


IEnumerator enumerator;
try
{
enumerator = list.GetEnumerator();
while(enumerator.MoveNext())
{
string name = (string)enumerator.Current;
Console.WriteLine("Hello " + name);
}
}
finally
{
if (enumerator != null)
enumerator.Dispose();
}

Section 28.4: Looping styles


While

The most trivial loop type. Only drawback is there is no intrinsic clue to know where you are in the loop.

loop while the condition satisfies


while(condition)
{
do something
}

Do

Similar to while, but the condition is evaluated at the end of the loop instead of the beginning. This results in
executing the loops at least once.

do
{
do something
} while(condition) /// loop while the condition satisfies

For

Another trivial loop style. While looping an index (i) gets increased and you can use it. It is usually used for handling
arrays.

for ( int i = 0; i < array.Count; i++ )


{
var currentItem = array[i];
/// do something with "currentItem"
}

Foreach

Modernized way of looping through IEnumarable objects. Good thing that you don't have to think about the index of the
item or the item count of the list.

foreach ( var item in someList )


{
/// do something with "item"

INFOBYTE CAREER INSTITUTE 121


}

Foreach Method

While the other styles are used for selecting or updating the elements in collections, this style is usually used for
calling a method straight away for all elements in a collection.

list.ForEach(item => item.DoSomething());

// or
list.ForEach(item => DoSomething(item));

// or using a method group


list.ForEach(Console.WriteLine);

// using an array
Array.ForEach(myArray, Console.WriteLine);

It is important to note that this method in only available on List<T> instances and as a static method on Array - it is not part
of Linq.

Linq Parallel Foreach

Just like Linq Foreach, except this one does the job in a parallel manner. Meaning that all the items in the collection will
run the given action at the same time, simultaneously.

collection.AsParallel().ForAll(item => item.DoSomething());

/// or
collection.AsParallel().ForAll(item => DoSomething(item));

Section 28.5: Nested loops


Print the multiplication table up to 5s for (int i = 1; i
<= 5; i++)
{
for (int j = 1; j <= 5; j++)
{
int product = i * j;
Console.WriteLine("{0} times {1} is {2}", i, j, product);
}
}

Section 28.6: continue


In addition to break, there is also the keyword continue. Instead of breaking completely the loop, it will simply skip the
current iteration. It could be useful if you don't want some code to be executed if a particular value is set.

Here's a simple example:

for (int i = 1; i <= 10; i++)


{
if (i < 9)
continue;

Console.WriteLine(i);

INFOBYTE CAREER INSTITUTE 122


}

Will result in:

9
10

Note: Continue is often most useful in while or do-while loops. For-loops, with well-defined exit conditions, may not benefit
as much.

Section 28.7: While loop


int n = 0;
while (n < 5)
{
Console.WriteLine(n);
n++;
}

Output:

0
1
2
3
4

IEnumerators can be iterated with a while loop:

Call a custom method that takes a count, and returns an IEnumerator for a list
of strings with the names of theh largest city metro areas.
IEnumerator<string> largestMetroAreas = GetLargestMetroAreas(4);

while (largestMetroAreas.MoveNext())
{
Console.WriteLine(largestMetroAreas.Current);
}

Sample output:

Tokyo/Yokohama
New York Metro
Sao Paulo
Seoul/Incheon

Section 28.8: break


Sometimes loop condition should be checked in the middle of the loop. The former is arguably more elegant than the
latter:

for (;;)
{

INFOBYTE CAREER INSTITUTE 123


// precondition code that can change the value of should_end_loop expression

if (should_end_loop)
break;

// do something
}

Alternative:

bool endLoop = false;


for (; !endLoop;)
{
// precondition code that can set endLoop flag

if (!endLoop)
{
// do something
}
}

Note: In nested loops and/or switch must use more than just a simple break.

INFOBYTE CAREER INSTITUTE 124


Chapter 29: Iterators
Section 29.1: Creating Iterators Using Yield
Iterators produce enumerators. In C#, enumerators are produced by defining methods, properties or indexers that
contain yield statements.

Most methods will return control to their caller through normal return statements, which disposes all state local to that
method. In contrast, methods that use yield statements allow them to return multiple values to the caller on request while
preserving local state in-between returning those values. These returned values constitute a sequence. There are two
types of yield statements used within iterators:

yield return, which returns control to the caller but preserves state. The callee will continue execution from this line
when control is passed back to it.

yield break, which functions similarly to a normal return statement - this signifies the end of the sequence.
Normal return statements themselves are illegal within an iterator block.

This example below demonstrates an iterator method that can be used to generate the Fibonacci sequence:

IEnumerable<int> Fibonacci(int count)


{
int prev = 1;
int curr = 1;

for (int i = 0; i < count; i++)


{
yield return prev;
int temp = prev + curr;
prev = curr;
curr = temp;
}
}

This iterator can then be used to produce an enumerator of the Fibonacci sequence that can be consumed by a
calling method. The code below demonstrates how the first ten terms within the Fibonacci sequence can be
enumerated:

void Main()
{
foreach (int term in Fibonacci(10))
{
Console.WriteLine(term);
}
}

Output

1
1
2
3
5
8
13
21

INFOBYTE CAREER INSTITUTE 125


34
55

Section 29.2: Simple Numeric Iterator Example


A common use-case for iterators is to perform some operation over a collection of numbers. The example below
demonstrates how each element within an array of numbers can be individually printed out to the console.

This is possible because arrays implement the IEnumerable interface, allowing clients to obtain an iterator for the array
using the GetEnumerator() method. This method returns an enumerator, which is a read-only, forward-only cursor over
each number in the array.

int[] numbers = { 1, 2, 3, 4, 5 };

IEnumerator iterator = numbers.GetEnumerator();

while (iterator.MoveNext())
{
Console.WriteLine(iterator.Current);
}

Output

1
2
3
4
5

It's also possible to achieve the same results using a foreach statement:

foreach (int number in numbers)


{
Console.WriteLine(number);
}

INFOBYTE CAREER INSTITUTE 126


Chapter 30: IEnumerable
IEnumerable is the base interface for all non-generic collections like ArrayList that can be enumerated.
IEnumerator<T> is the base interface for all generic enumerators like List<>.

IEnumerable is an interface which implements the method GetEnumerator. The GetEnumerator method returns an
IEnumerator which provides options to iterate through the collection like foreach.

Section 30.1: IEnumerable with custom Enumerator


Implementing the IEnumerable interface allows classes to be enumerated in the same way as BCL collections. This
requires extending the Enumerator class which tracks the state of the enumeration.

Other than iterating over a standard collection, examples include:

Using ranges of numbers based on a function rather than a collection of objects


Implementing different iteration algorithms over collections, like DFS or BFS on a graph collection

public static void Main(string[] args) {

foreach (var coffee in new CoffeeCollection()) {


Console.WriteLine(coffee);
}
}

public class CoffeeCollection : IEnumerable {


private CoffeeEnumerator enumerator;

public CoffeeCollection() {
enumerator = new CoffeeEnumerator();
}

public IEnumerator GetEnumerator() {


return enumerator;
}

public class CoffeeEnumerator : IEnumerator {


string[] beverages = new string[3] { "espresso", "macchiato", "latte" }; int currentIndex = -1;

public object Current {


get {
return beverages[currentIndex];
}
}

public bool MoveNext() {


currentIndex++;

if (currentIndex < beverages.Length) {


return true;
}

return false;
}

public void Reset() {


currentIndex = 0;
}

INFOBYTE CAREER INSTITUTE 127


}
}

Section 30.2: IEnumerable<int>


In its most basic form, an object that implements IEnumerable represents a series of objects. The objects in
question can be iterated using the c# foreach keyword.

In the example below, the object sequenceOfNumbers implements IEnumerable. It represents a series of integers.
The foreach loop iterates through each in turn.

int AddNumbers(IEnumerable<int> sequenceOfNumbers) { int


returnValue = 0;
foreach(int i in sequenceOfNumbers) {
returnValue += i;
}
return returnValue;
}

INFOBYTE CAREER INSTITUTE 128


Chapter 31: Value type vs Reference type
Section 31.1: Passing by reference using ref keyword
From the documentation :

In C#, arguments can be passed to parameters either by value or by reference. Passing by reference enables
function members, methods, properties, indexers, operators, and constructors to change the value of the
parameters and have that change persist in the calling environment. To pass a parameter by reference, use
the ref or out keyword.

The difference between ref and out is that out means that the passed parameter has to be assigned before the
function ends.in contrast parameters passed with ref can be changed or left unchanged.

using System;

class Program
{
static void Main(string[] args)
{
int a = 20;
Console.WriteLine("Inside Main - Before Callee: a = {0}", a); Callee(a);

Console.WriteLine("Inside Main - After Callee: a = {0}", a);

Console.WriteLine("Inside Main - Before CalleeRef: a = {0}", a);


CalleeRef(ref a);
Console.WriteLine("Inside Main - After CalleeRef: a = {0}", a);

Console.WriteLine("Inside Main - Before CalleeOut: a = {0}", a); CalleeOut(out a);

Console.WriteLine("Inside Main - After CalleeOut: a = {0}", a);

Console.ReadLine();
}

static void Callee(int a)


{
a = 5;
Console.WriteLine("Inside Callee a : {0}", a);
}

static void CalleeRef(ref int a)


{
a = 6;
Console.WriteLine("Inside CalleeRef a : {0}", a);
}

static void CalleeOut(out int a)


{
a = 7;
Console.WriteLine("Inside CalleeOut a : {0}", a);
}
}

Output :

INFOBYTE CAREER INSTITUTE 129


Inside Main - Before Callee: a = 20
Inside Callee a : 5
Inside Main - After Callee: a = 20
Inside Main - Before CalleeRef: a = 20
Inside CalleeRef a : 6
Inside Main - After CalleeRef: a = 6
Inside Main - Before CalleeOut: a = 6
Inside CalleeOut a : 7
Inside Main - After CalleeOut: a = 7

Section 31.2: Changing values elsewhere


public static void Main(string[] args)
{
var studentList = new List<Student>();
studentList.Add(new Student("Scott", "Nuke"));
studentList.Add(new Student("Vincent", "King"));
studentList.Add(new Student("Craig", "Bertt"));

// make a separate list to print out later


var printingList = studentList; // this is a new list object, but holding the same student objects inside it

oops, we've noticed typos in the names, so we fix those


studentList[0].LastName = "Duke"; studentList[1].LastName = "Kong";
studentList[2].LastName = "Brett";

okay, we now print the list


PrintPrintingList(printingList);
}

private static void PrintPrintingList(List<Student> students)


{
foreach (Student student in students)
{
Console.WriteLine(string.Format("{0} {1}", student.FirstName, student.LastName));
}
}

You'll notice that even though the printingList list was made before the corrections to student names after the typos,
the PrintPrintingList method still prints out the corrected names:

Scott Duke
Vincent Kong
Craig Brett

This is because both lists hold a list of references to the same students. SO changing the underlying student object
propogates to usages by either list.

Here's what the student class would look like.

public class Student


{
public string FirstName { get; set; }
public string LastName { get; set; }

public Student(string firstName, string lastName)


{

INFOBYTE CAREER INSTITUTE 130


this.FirstName = firstName;
this.LastName = lastName;
}
}

Section 31.3: ref vs out parameters


Code

class Program
{
static void Main(string[] args)
{
int a = 20;
Console.WriteLine("Inside Main - Before Callee: a = {0}", a); Callee(a);

Console.WriteLine("Inside Main - After Callee: a = {0}", a); Console.WriteLine();

Console.WriteLine("Inside Main - Before CalleeRef: a = {0}", a);


CalleeRef(ref a);
Console.WriteLine("Inside Main - After CalleeRef: a = {0}", a);
Console.WriteLine();

Console.WriteLine("Inside Main - Before CalleeOut: a = {0}", a); CalleeOut(out a);

Console.WriteLine("Inside Main - After CalleeOut: a = {0}", a); Console.ReadLine();

static void Callee(int a)


{
a += 5;
Console.WriteLine("Inside Callee a : {0}", a);
}

static void CalleeRef(ref int a)


{
a += 10;
Console.WriteLine("Inside CalleeRef a : {0}", a);
}

static void CalleeOut(out int a)


{
can't use a+=15 since for this method 'a' is not intialized only declared in the method
declaration
a = 25; //has to be initialized
Console.WriteLine("Inside CalleeOut a : {0}", a);
}
}

Output

Inside Main - Before Callee: a = 20


Inside Callee a : 25
Inside Main - After Callee: a = 20

Inside Main - Before CalleeRef: a = 20


Inside CalleeRef a : 30
Inside Main - After CalleeRef: a = 30

INFOBYTE CAREER INSTITUTE 131


Inside Main - Before CalleeOut: a = 30
Inside CalleeOut a : 25
Inside Main - After CalleeOut: a = 25

Section 31.4: Assignment


var a = new List<int>();
var b = a;
a.Add(5);
Console.WriteLine(a.Count); // prints 1
Console.WriteLine(b.Count); // prints 1 as well

Assigning to a variable of a List<int> does not create a copy of the List<int>. Instead, it copies the reference to the
List<int>. We call types that behave this way reference types.

Section 31.5: Di erence with method parameters ref and out


There are two possible ways to pass a value type by reference: ref and out. The difference is that by passing it with ref the
value must be initialized but not when passing it with out. Using out ensures that the variable has a value after the method
call:

public void ByRef(ref int value)


{
Console.WriteLine(nameof(ByRef) + value);
value += 4;
Console.WriteLine(nameof(ByRef) + value);
}

public void ByOut(out int value)


{
value += 4 // CS0269: Use of unassigned out parameter `value'
Console.WriteLine(nameof(ByOut) + value); // CS0269: Use of unassigned out parameter `value'

value = 4;
Console.WriteLine(nameof(ByOut) + value);
}

public void TestOut()


{
int outValue1;
ByOut(out outValue1); // prints 4

int outValue2 = 10; // does not make any sense for out ByOut(out
outValue2); // prints 4
}

public void TestRef()


{
int refValue1;
ByRef(ref refValue1); // S0165 Use of unassigned local variable 'refValue'

int refValue2 = 0;
ByRef(ref refValue2); // prints 0 and 4

int refValue3 = 10;


ByRef(ref refValue3); // prints 10 and 14
}

The catch is that by using out the parameter must be initialized before leaving the method, therefore the following

INFOBYTE CAREER INSTITUTE 132


method is possible with ref but not with out:

public void EmtyRef(bool condition, ref int value)


{
if (condition)
{
value += 10;
}
}

public void EmtyOut(bool condition, out int value)


{
if (condition)
{
value = 10;
}
} //CS0177: The out parameter 'value' must be assigned before control leaves the current method

This is because if condition does not hold, value goes unassigned.

Section 31.6: Passing by reference


If you want the Value Types vs Reference Types in methods example to work properly, use the ref keyword in your
method signature for the parameter you want to pass by reference, as well as when you call the method.

public static void Main(string[] args)


{
...
DoubleNumber(ref number); // calling code
Console.WriteLine(number); // outputs 8
...
}

public void DoubleNumber(ref int number)


{
number += number;
}

Making these changes would make the number update as expected, meaning the console output for number would be 8.

INFOBYTE CAREER INSTITUTE 133


Chapter 32: Built-in Types
Section 32.1: Conversion of boxed value types
Boxed value types can only be unboxed into their original Type, even if a conversion of the two Types is valid, e.g.:

object boxedInt = (int)1; // int boxed in an object

long unboxedInt1 = (long)boxedInt; // invalid cast

This can be avoided by first unboxing into the original Type, e.g.:

long unboxedInt2 = (long)(int)boxedInt; // valid

Section 32.2: Comparisons with boxed value types


If value types are assigned to variables of type object they are boxed - the value is stored in an instance of a
System.Object. This can lead to unintended consequences when comparing values with ==, e.g.:

object left = (int)1; // int in an object box


object right = (int)1; // int in an object box

var comparison1 = left == right; // false

This can be avoided by using the overloaded Equals method, which will give the expected result.

var comparison2 = left.Equals(right); // true

Alternatively, the same could be done by unboxing the left and right variables so that the int values are
compared:

var comparison3 = (int)left == (int)right; // true

Section 32.3: Immutable reference type - string


assign string from a string literal string s =
"hello";

assign string from an array of characters


char[] chars = new char[] { 'h', 'e', 'l', 'l', 'o' }; string s = new string(chars, 0,
chars.Length);

assign string from a char pointer, derived from a string string s;

unsafe
{
fixed (char* charPointer = "hello")
{
s = new string(charPointer);
}
}

INFOBYTE CAREER INSTITUTE 134


Section 32.4: Value type - char
single character s char
c = 's';

character s: casted from integer value char c =


(char)115;

unicode character: single character s char c =


'\u0073';

unicode character: smiley face


char c = '\u263a';

Section 32.5: Value type - short, int, long (signed 16 bit, 32


bit, 64 bit integers)
assigning a signed short to its minimum value short s = -
32768;

assigning a signed short to its maximum value short s =


32767;

assigning a signed int to its minimum value int i = -


2147483648;

assigning a signed int to its maximum value int i =


2147483647;

assigning a signed long to its minimum value (note the long postfix) long l = -
9223372036854775808L;

assigning a signed long to its maximum value (note the long postfix) long l =
9223372036854775807L;

It is also possible to make these types nullable, meaning that additionally to the usual values, null can be assigned, too. If
a variable of a nullable type is not initialized, it will be null instead of 0. Nullable types are marked by adding a question
mark (?) after the type.

int a; //This is now 0.


int? b; //This is now null.

Section 32.6: Value type - ushort, uint, ulong (unsigned 16


bit, 32 bit, 64 bit integers)
assigning an unsigned short to its minimum value ushort s = 0;

assigning an unsigned short to its maximum value ushort s =


65535;

assigning an unsigned int to its minimum value uint i = 0;

assigning an unsigned int to its maximum value uint i =


4294967295;

INFOBYTE CAREER INSTITUTE 135


assigning an unsigned long to its minimum value (note the unsigned long postfix) ulong l = 0UL;

assigning an unsigned long to its maximum value (note the unsigned long postfix) ulong l =
18446744073709551615UL;

It is also possible to make these types nullable, meaning that additionally to the usual values, null can be assigned, too. If
a variable of a nullable type is not initialized, it will be null instead of 0. Nullable types are marked by adding a question
mark (?) after the type.

uint a; //This is now 0.


uint? b; //This is now null.

Section 32.7: Value type - bool


default value of boolean is false bool b;

//default value of nullable boolean is null bool? z;

b = true;
if(b) {
Console.WriteLine("Boolean has true value");
}

The bool keyword is an alias of System.Boolean. It is used to declare variables to store the Boolean values, true and false.

INFOBYTE CAREER INSTITUTE 136


Chapter 33: Aliases of built-in types
Section 33.1: Built-In Types Table
The following table shows the keywords for built-in C# types, which are aliases of predefined types in the System
namespaces.

C# Type .NET Framework Type


bool System.Boolean
byte System.Byte
sbyte System.SByte
char System.Char
decimal System.Decimal
double System.Double
float System.Single
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
object System.Object
short System.Int16
ushort System.UInt16
string System.String

The C# type keywords and their aliases are interchangeable. For example, you can declare an integer variable by
using either of the following declarations:

int number = 123;


System.Int32 number = 123;

INFOBYTE CAREER INSTITUTE 137


Chapter 34: Anonymous types
Section 34.1: Anonymous vs dynamic
Anonymous types allow the creation of objects without having to explicitly define their types ahead of time, while
maintaining static type checking.

var anon = new { Value = 1 };


Console.WriteLine(anon.Id); // compile time error

Conversely, dynamic has dynamic type checking, opting for runtime errors, instead of compile-time errors.

dynamic val = "foo";


Console.WriteLine(val.Id); // compiles, but throws runtime error

Section 34.2: Creating an anonymous type


Since anonymous types are not named, variables of those types must be implicitly typed ( var).

var anon = new { Foo = 1, Bar = 2 };


anon.Foo == 1
anon.Bar == 2

If the member names are not specified, they are set to the name of the property/variable used to initialize the
object.

int foo = 1;
int bar = 2;
var anon2 = new { foo, bar };
anon2.foo == 1
anon2.bar == 2

Note that names can only be omitted when the expression in the anonymous type declaration is a simple property
access; for method calls or more complex expressions, a property name must be specified.

string foo = "some string";


var anon3 = new { foo.Length };
// anon3.Length == 11
var anon4 = new { foo.Length <= 10 ? "short string" : "long string" }; // compiler error - Invalid
anonymous type member declarator.
var anon5 = new { Description = foo.Length <= 10 ? "short string" : "long string" }; // OK

Section 34.3: Anonymous type equality


Anonymous type equality is given by the Equals instance method. Two objects are equal if they have the same type and
equal values (through a.Prop.Equals(b.Prop)) for every property.

var anon = new { Foo = 1, Bar = 2 };


var anon2 = new { Foo = 1, Bar = 2 };
var anon3 = new { Foo = 5, Bar = 10 };
var anon3 = new { Foo = 5, Bar = 10 };
var anon4 = new { Bar = 2, Foo = 1 };
anon.Equals(anon2) == true
anon.Equals(anon3) == false

INFOBYTE CAREER INSTITUTE 138


// anon.Equals(anon4) == false (anon and anon4 have different types, see below)

Two anonymous types are considered the same if and only if their properties have the same name and type and
appear in the same order.

var anon = new { Foo = 1, Bar = 2 };


var anon2 = new { Foo = 7, Bar = 1 };
var anon3 = new { Bar = 1, Foo = 3 };
var anon4 = new { Fa = 1, Bar = 2 };
anon and anon2 have the same type
anon and anon3 have diferent types (Bar and Foo appear in different orders)
anon and anon4 have different types (property names are different)

Section 34.4: Generic methods with anonymous types


Generic methods allow the use of anonymous types through type inference.

void Log<T>(T obj) {


// ...
}
Log(new { Value = 10 });

This means LINQ expressions can be used with anonymous types:

var products = new[] {


new { Amount = 10, Id = 0 },
new { Amount = 20, Id = 1 },
new { Amount = 15, Id = 2 }
};
var idsByAmount = products.OrderBy(x => x.Amount).Select(x => x.Id); // idsByAmount: 0,
2, 1

Section 34.5: Instantiating generic types with anonymous


types
Using generic constructors would require the anonymous types to be named, which is not possible. Alternatively,
generic methods may be used to allow type inference to occur.

var anon = new { Foo = 1, Bar = 2 };


var anon2 = new { Foo = 5, Bar = 10 };
List<T> CreateList<T>(params T[] items) {
return new List<T>(items);
}

var list1 = CreateList(anon, anon2);

In the case of List<T>, implicitly typed arrays may be converted to a List<T> through the ToList LINQ method:

var list2 = new[] {anon, anon2}.ToList();

Section 34.6: Implicitly typed arrays


Arrays of anonymous types may be created with implicit typing.

var arr = new[] {


new { Id = 0 },

INFOBYTE CAREER INSTITUTE 139


new { Id = 1 }
};

INFOBYTE CAREER INSTITUTE 140


Chapter 35: Dynamic type
Section 35.1: Creating a dynamic object with properties
using System;
using System.Dynamic;

dynamic info = new ExpandoObject();


info.Id = 123;
info.Another = 456;

Console.WriteLine(info.Another);
// 456

Console.WriteLine(info.DoesntExist);
// Throws RuntimeBinderException

Section 35.2: Creating a dynamic variable


dynamic foo = 123;
Console.WriteLine(foo + 234);
// 357 Console.WriteLine(foo.ToUpper())
// RuntimeBinderException, since int doesn't have a ToUpper method

foo = "123";
Console.WriteLine(foo + 234);
// 123234
Console.WriteLine(foo.ToUpper()):
// NOW A STRING

Section 35.3: Returning dynamic


using System;

public static void Main()


{
var value = GetValue();
Console.WriteLine(value);
// dynamics are useful!
}

private static dynamic GetValue()


{
return "dynamics are useful!";
}

Section 35.4: Handling Specific Types Unknown at


Compile Time
The following output equivalent results:

class IfElseExample
{
public string DebugToString(object a)
{
if (a is StringBuilder)

INFOBYTE CAREER INSTITUTE 141


{
return DebugToStringInternal(a as StringBuilder);
}
else if (a is List<string>)
{
return DebugToStringInternal(a as List<string>);
}
else
{
return a.ToString();
}
}

private string DebugToStringInternal(object a)


{
// Fall Back
return a.ToString();
}

private string DebugToStringInternal(StringBuilder sb)


{
return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value:
{sb.ToString()}";
}

private string DebugToStringInternal(List<string> list)


{
return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" +
string.Join(Environment.NewLine + "\t", list.ToArray())}";
}
}

class DynamicExample
{
public string DebugToString(object a)
{
return DebugToStringInternal((dynamic)a);
}

private string DebugToStringInternal(object a)


{
// Fall Back
return a.ToString();
}

private string DebugToStringInternal(StringBuilder sb)


{
return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value:
{sb.ToString()}";
}

private string DebugToStringInternal(List<string> list)


{
return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" +
string.Join(Environment.NewLine + "\t", list.ToArray())}";
}
}

The advantage to the dynamic, is adding a new Type to handle just requires adding an overload of
DebugToStringInternal of the new type. Also eliminates the need to manually cast it to the type as well.

INFOBYTE CAREER INSTITUTE 142


Chapter 36: Type Conversion
Section 36.1: Explicit Type Conversion
using System;
namespace TypeConversionApplication
{
class ExplicitConversion
{
static void Main(string[] args)
{
double d = 5673.74;
int i;

cast double to int. i =


(int)d; Console.WriteLine(i);
Console.ReadKey();

}
}
}

Section 36.2: MSDN implicit operator example


class Digit
{
public Digit(double d) { val = d; }
public double val;

User-defined conversion from Digit to double public static


implicit operator double(Digit d)
{
Console.WriteLine("Digit to double implict conversion called"); return d.val;

}
User-defined conversion from double to Digit
public static implicit operator Digit(double d)
{
Console.WriteLine("double to Digit implict conversion called"); return new Digit(d);

}
}

class Program
{
static void Main(string[] args)
{
Digit dig = new Digit(7);
//This call invokes the implicit "double" operator
double num = dig;
//This call invokes the implicit "Digit" operator
Digit dig2 = 12;
Console.WriteLine("num = {0} dig2 = {1}", num, dig2.val);
Console.ReadLine();
}
}

Output:

INFOBYTE CAREER INSTITUTE 143


Digit to double implict conversion called
double to Digit implict conversion called
num = 7 dig2 = 12

Live Demo on .NET Fiddle

INFOBYTE CAREER INSTITUTE 144


Chapter 37: Casting
Section 37.1: Checking compatibility without casting
If you need to know whether a value's type extends or implements a given type, but you don't want to actually cast it as
that type, you can use the is operator.

if(value is int)
{
Console.WriteLine(value + "is an int");
}

Section 37.2: Cast an object to a base type


Given the following definitions :

public interface IMyInterface1


{
string GetName();
}

public interface IMyInterface2


{
string GetName();
}

public class MyClass : IMyInterface1, IMyInterface2


{
string IMyInterface1.GetName()
{
return "IMyInterface1";
}

string IMyInterface2.GetName()
{
return "IMyInterface2";
}
}

Casting an object to a base type example :

MyClass obj = new MyClass();

IMyInterface1 myClass1 = (IMyInterface1)obj;


IMyInterface2 myClass2 = (IMyInterface2)obj;

Console.WriteLine("I am : {0}", myClass1.GetName());


Console.WriteLine("I am : {0}", myClass2.GetName());

Outputs :
I am : IMyInterface1
I am : IMyInterface2

Section 37.3: Conversion Operators


In C#, types can define custom Conversion Operators, which allow values to be converted to and from other types
using either explicit or implicit casts. For example, consider a class that is meant to represent a JavaScript

INFOBYTE CAREER INSTITUTE 145


expression:

public class JsExpression


{
private readonly string expression;
public JsExpression(string rawExpression)
{
this.expression = rawExpression;
}
public override string ToString()
{
return this.expression;
}
public JsExpression IsEqualTo(JsExpression other)
{
return new JsExpression("(" + this + " == " + other + ")");
}
}

If we wanted to create a JsExpression representing a comparison of two JavaScript values, we could do something like
this:

JsExpression intExpression = new JsExpression("-1"); JsExpression


doubleExpression = new JsExpression("-1.0");
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

But we can add some explicit conversion operators to JsExpression, to allow a simple conversion when using explicit
casting.

public static explicit operator JsExpression(int value)


{
return new JsExpression(value.ToString());
}
public static explicit operator JsExpression(double value)
{
return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = (JsExpression)(-1); JsExpression
doubleExpression = (JsExpression)(-1.0);
Console.WriteLine(intExpression.IsEqualTo(doubleExpression)); // (-1 == -1.0)

Or, we could change these operators to implicit to make the syntax much simpler.

public static implicit operator JsExpression(int value)


{
return new JsExpression(value.ToString());
}
public static implicit operator JsExpression(double value)
{
return new JsExpression(value.ToString());
}

// Usage:
JsExpression intExpression = -1;
Console.WriteLine(intExpression.IsEqualTo(-1.0)); // (-1 == -1.0)

INFOBYTE CAREER INSTITUTE 146


Section 37.4: LINQ Casting operations
Suppose you have types like the following:

interface IThing { }
class Thing : IThing { }

LINQ allows you to create a projection that changes the compile-time generic type of an IEnumerable<> via the
Enumerable.Cast<>() and Enumerable.OfType<>() extension methods.

IEnumerable<IThing> things = new IThing[] {new Thing()};


IEnumerable<Thing> things2 = things.Cast<Thing>();
IEnumerable<Thing> things3 = things.OfType<Thing>();

When things2 is evaluated, the Cast<>() method will try to cast all of the values in things into Things. If it
encounters a value that cannot be cast, an InvalidCastException will be thrown.

When things3 is evaluated, the OfType<>() method will do the same, except that if it encounters a value that cannot
be cast, it will simply omit that value rather than throw an exception.

Due to the generic type of these methods, they cannot invoke Conversion Operators or perform numeric
conversions.

double[] doubles = new[]{1,2,3}.Cast<double>().ToArray(); // Throws InvalidCastException

You can simply perform a cast inside a .Select() as a workaround:

double[] doubles = new[]{1,2,3}.Select(i => (double)i).ToArray();

Section 37.5: Explicit Casting


If you know that a value is of a specific type, you can explicitly cast it to that type in order to use it in a context
where that type is needed.

object value = -1;


int number = (int) value;
Console.WriteLine(Math.Abs(number));

If we tried passing value directly to Math.Abs(), we would get a compile-time exception because Math.Abs() doesn't
have an overload that takes an object as a parameter.

If value could not be cast to an int, then the second line in this example would throw an InvalidCastException

Section 37.6: Safe Explicit Casting (`as` operator)


If you aren't sure whether a value is of the type you think it is, you can safely cast it using the as operator. If the value
is not of that type, the resulting value will be null.

object value = "-1";


int? number = value as int?;
if(number != null)
{
Console.WriteLine(Math.Abs(number.Value));
}

INFOBYTE CAREER INSTITUTE 147


Note that null values have no type, so the as keyword will safely yield null when casting any null value.

Section 37.7: Implicit Casting


A value will automatically be cast to the appropriate type if the compiler knows that it can always be converted to that
type.

int number = -1;


object value = number;
Console.WriteLine(value);

In this example, we didn't need to use the typical explicit casting syntax because the compiler knows all ints can be cast
to objects. In fact, we could avoid creating variables and pass -1 directly as the argument of Console.WriteLine() that
expects an object.

Console.WriteLine(-1);

Section 37.8: Explicit Numeric Conversions


Explicit casting operators can be used to perform conversions of numeric types, even though they don't extend or
implement one another.

double value = -1.1;


int number = (int) value;

Note that in cases where the destination type has less precision than the original type, precision will be lost. For
example, -1.1 as a double value in the above example becomes -1 as an integer value.

Also, numeric conversions rely on compile-time types, so they won't work if the numeric types have been "boxed" into
objects.

object value = -1.1;


int number = (int) value; // throws InvalidCastException

INFOBYTE CAREER INSTITUTE 148


Chapter 38: Nullable types
Section 38.1: Initialising a nullable
For null values:

Nullable<int> i = null;

Or:

int? i = null;

Or:

var i = (int?)null;

For non-null values:

Nullable<int> i = 0;

Or:

int? i = 0;

Section 38.2: Check if a Nullable has a value


int? i = null;

if (i != null)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}

Which is the same as:

if (i.HasValue)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}

Section 38.3: Get the value of a nullable type


Given following nullable int

int? i = 10;

INFOBYTE CAREER INSTITUTE 149


In case default value is needed, you can assign one using null coalescing operator, GetValueOrDefault method or check
if nullable int HasValue before assignment.

int j = i ?? 0;
int j = i.GetValueOrDefault(0);
int j = i.HasValue ? i.Value : 0;

The following usage is always unsafe. If i is null at runtime, a System.InvalidOperationException will be thrown.
At design time, if a value is not set, you'll get a Use of unassigned local variable 'i' error.

int j = i.Value;

Section 38.4: Getting a default value from a nullable


The .GetValueOrDefault() method returns a value even if the .HasValue property is false (unlike the Value property,
which throws an exception).

class Program
{
static void Main()
{
int? nullableExample = null;
int result = nullableExample.GetValueOrDefault();
Console.WriteLine(result); // will output the default value for int - 0
int secondResult = nullableExample.GetValueOrDefault(1);
Console.WriteLine(secondResult) // will output our specified default - 1
int thirdResult = nullableExample ?? 1;
Console.WriteLine(secondResult) // same as the GetValueOrDefault but a bit shorter
}
}

Output:

0
1

Section 38.5: Default value of nullable types is null


public class NullableTypesExample
{
static int? _testValue;

public static void Main()


{
if(_testValue == null)
Console.WriteLine("null");
else
Console.WriteLine(_testValue.ToString());
}
}

Output:

null

INFOBYTE CAREER INSTITUTE 150


Section 38.6: E ective usage of underlying Nullable<T>
argument
Any nullable type is a generic type. And any nullable type is a value type.

There are some tricks which allow to effectively use the result of the Nullable.GetUnderlyingType method when
creating code related to reflection/code-generation purposes:

public static class TypesHelper {


public static bool IsNullable(this Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType);
}
public static bool IsNullable(this Type type, out Type underlyingType) { underlyingType =
Nullable.GetUnderlyingType(type);
return underlyingType != null;
}
public static Type GetNullable(Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type);
}
public static bool IsExactOrNullable(this Type type, Func<Type, bool> predicate) { Type underlyingType;

if(IsNullable(type, out underlyingType))


return IsExactOrNullable(underlyingType, predicate); return
predicate(type);
}
public static bool IsExactOrNullable<T>(this Type type)
where T : struct {
return IsExactOrNullable(type, t => Equals(t, typeof(T)));
}
}

The usage:

Type type = typeof(int).GetNullable();


Console.WriteLine(type.ToString());

if(type.IsNullable())
Console.WriteLine("Type is nullable.");
Type underlyingType;
if(type.IsNullable(out underlyingType))
Console.WriteLine("The underlying type is " + underlyingType.Name + ".");
if(type.IsExactOrNullable<int>())
Console.WriteLine("Type is either exact or nullable Int32.");
if(!type.IsExactOrNullable(t => t.IsEnum))
Console.WriteLine("Type is neither exact nor nullable enum.");

Output:

System.Nullable`1[System.Int32]
Type is nullable.
The underlying type is Int32.
Type is either exact or nullable Int32.
Type is neither exact nor nullable enum.

PS. The NullableTypesCache is defined as follows:

INFOBYTE CAREER INSTITUTE 151


static class NullableTypesCache {
readonly static ConcurrentDictionary<Type, Type> cache = new ConcurrentDictionary<Type, Type>();

static NullableTypesCache() {
cache.TryAdd(typeof(byte), typeof(Nullable<byte>));
cache.TryAdd(typeof(short), typeof(Nullable<short>));
cache.TryAdd(typeof(int), typeof(Nullable<int>));
cache.TryAdd(typeof(long), typeof(Nullable<long>));
cache.TryAdd(typeof(float), typeof(Nullable<float>));
cache.TryAdd(typeof(double), typeof(Nullable<double>));
cache.TryAdd(typeof(decimal), typeof(Nullable<decimal>));
cache.TryAdd(typeof(sbyte), typeof(Nullable<sbyte>));
cache.TryAdd(typeof(ushort), typeof(Nullable<ushort>));
cache.TryAdd(typeof(uint), typeof(Nullable<uint>));
cache.TryAdd(typeof(ulong), typeof(Nullable<ulong>));
//...
}
readonly static Type NullableBase = typeof(Nullable<>); internal static
Type Get(Type type) {
// Try to avoid the expensive MakeGenericType method call
return cache.GetOrAdd(type, t => NullableBase.MakeGenericType(t));
}
}

Section 38.7: Check if a generic type parameter is a nullable


type
public bool IsTypeNullable<T>()
{
return Nullable.GetUnderlyingType( typeof(T) )!=null;
}

INFOBYTE CAREER INSTITUTE 152


Chapter 39: Constructors and Finalizers
Constructors are methods in a class that are invoked when an instance of that class is created. Their main
responsibility is to leave the new object in a useful and consistent state.

Destructors/Finalizers are methods in a class that are invoked when an instance of that is destroyed. In C# they are
rarely explicitely written/used.

Section 39.1: Static constructor


A static constructor is called the first time any member of a type is initialized, a static class member is called or a
static method. The static constructor is thread safe. A static constructor is commonly used to:

Initialize static state, that is state which is shared across different instances of the same class.
Create a singleton

Example:

class Animal
{
* A static constructor is executed only once,
when a class is first accessed.
* A static constructor cannot have any access modifiers
* A static constructor cannot have any parameters static
Animal()
{
Console.WriteLine("Animal initialized");
}

Instance constructor, this is executed every time the class is created public Animal()

{
Console.WriteLine("Animal created");
}

public static void Yawn()


{
Console.WriteLine("Yawn!");
}
}

var turtle = new Animal();


var giraffe = new Animal();

Output:

Animal initialized
Animal created
Animal created

View Demo

If the first call is to a static method, the static constructor is invoked without the instance constructor. This is OK,
because the static method can't access instance state anyways.

INFOBYTE CAREER INSTITUTE 153


Animal.Yawn();

This will output:

Animal initialized
Yawn!

See also Exceptions in static constructors and Generic Static Constructors .

Singleton example:

public class SessionManager


{
public static SessionManager Instance;

static SessionManager()
{
Instance = new SessionManager();
}
}

Section 39.2: Singleton constructor pattern


public class SingletonClass
{
public static SingletonClass Instance { get; } = new SingletonClass();

private SingletonClass()
{
// Put custom constructor code here
}
}

Because the constructor is private, no new instances of SingletonClass can be made by consuming code. The only way to
access the single instance of SingletonClass is by using the static property SingletonClass.Instance.

The Instance property is assigned by a static constructor that the C# compiler generates. The .NET runtime
guarantees that the static constructor is run at most once and is run before Instance is first read. Therefore, all
synchronization and initialization concerns are carried out by the runtime.

Note, that if the static constructor fails the Singleton class becomes permanently unusable for the life of the
AppDomain.

Also, the static constructor is not guaranteed to run at the time of the first access of Instance. Rather, it will run at some
point before that. This makes the time at which initialization happens non-deterministic. In practical cases the JIT often
calls the static constructor during compilation (not execution) of a method referencing Instance. This is a performance
optimization.

See the Singleton Implementations page for other ways to implement the singleton pattern.

Section 39.3: Default Constructor


When a type is defined without a constructor:

INFOBYTE CAREER INSTITUTE 154


public class Animal
{
}

then the compiler generates a default constructor equivalent to the following:

public class Animal


{
public Animal() {}
}

The definition of any constructor for the type will suppress the default constructor generation. If the type were
defined as follows:

public class Animal


{
public Animal(string name) {}
}

then an Animal could only be created by calling the declared constructor.

// This is valid
var myAnimal = new Animal("Fluffy");
// This fails to compile
var unnamedAnimal = new Animal();

For the second example, the compiler will display an error message:

'Animal' does not contain a constructor that takes 0 arguments

If you want a class to have both a parameterless constructor and a constructor that takes a parameter, you can do it by
explicitly implementing both constructors.

public class Animal


{

public Animal() {} //Equivalent to a default constructor.


public Animal(string name) {}
}

The compiler will not be able to generate a default constructor if the class extends another class which doesn't have a
parameterless constructor. For example, if we had a class Creature:

public class Creature


{
public Creature(Genus genus) {}
}

then Animal defined as class Animal : Creature {} would not compile.

Section 39.4: Forcing a static constructor to be called


While static constructors are always called before the first usage of a type it's sometimes useful to be able to force them
to be called and the RuntimeHelpers class provide an helper for it:

INFOBYTE CAREER INSTITUTE 155


using System.Runtime.CompilerServices;
// ...
RuntimeHelpers.RunClassConstructor(typeof(Foo).TypeHandle);

Remark: All static initialization (fields initializers for example) will run, not only the constructor itself.

Potential usages: Forcing initialization during the splash screen in an UI application or ensuring that a static
constructor doesn't fail in an unit test.

Section 39.5: Calling a constructor from another constructor


public class Animal
{
public string Name { get; set; }

public Animal() : this("Dog")


{
}

public Animal(string name)


{
Name = name;
}
}

var dog = new Animal(); // dog.Name will be set to "Dog" by default.


var cat = new Animal("Cat"); // cat.Name is "Cat", the empty constructor is not called.

Section 39.6: Calling the base class constructor


A constructor of a base class is called before a constructor of a derived class is executed. For example, if Mammal
extends Animal, then the code contained in the constructor of Animal is called first when creating an instance of a
Mammal.

If a derived class doesn't explicitly specify which constructor of the base class should be called, the compiler
assumes the parameterless constructor.

public class Animal


{
public Animal() { Console.WriteLine("An unknown animal gets born."); } public Animal(string
name) { Console.WriteLine(name + " gets born"); }
}

public class Mammal : Animal


{
public Mammal(string name)
{
Console.WriteLine(name + " is a mammal.");
}
}

In this case, instantiating a Mammal by calling new Mammal("George the Cat") will print

An unknown animal gets born.


George the Cat is a mammal.

INFOBYTE CAREER INSTITUTE 156


View Demo

Calling a different constructor of the base class is done by placing : base(args) between the constructor's
signature and its body:

public class Mammal : Animal


{
public Mammal(string name) : base(name)
{
Console.WriteLine(name + " is a mammal.");
}
}

Calling new Mammal("George the Cat") will now print:

George the Cat gets born.


George the Cat is a mammal.

View Demo

Section 39.7: Finalizers on derived classes


When an object graph is finalized, the order is the reverse of the construction. E.g. the super-type is finalized before the
base-type as the following code demonstrates:

class TheBaseClass
{
~TheBaseClass()
{
Console.WriteLine("Base class finalized!");
}
}

class TheDerivedClass : TheBaseClass


{
~TheDerivedClass()
{
Console.WriteLine("Derived class finalized!");
}
}

//Don't assign to a variable


//to make the object unreachable
new TheDerivedClass();

//Just to make the example work;


//this is otherwise NOT recommended!
GC.Collect();

//Derived class finalized!


//Base class finalized!

Section 39.8: Exceptions in static constructors


If a static constructor throws an exception, it is never retried. The type is unusable for the lifetime of the AppDomain. Any
further usages of the type will raise a TypeInitializationException wrapped around the original

INFOBYTE CAREER INSTITUTE 157


exception.

public class Animal


{
static Animal()
{
Console.WriteLine("Static ctor");
throw new Exception();
}

public static void Yawn() {}


}

try
{
Animal.Yawn();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}

try
{
Animal.Yawn();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}

This will output:

Static ctor

System.TypeInitializationException: The type initializer for 'Animal' threw an exception. --->


System.Exception: Exception of type 'System.Exception' was thrown.

[...]

System.TypeInitializationException: The type initializer for 'Animal' threw an exception. --->


System.Exception: Exception of type 'System.Exception' was thrown.

where you can see that the actual constructor is only executed once, and the exception is re-used.

Section 39.9: Constructor and Property Initialization


Shall the property value's assignment be executed before or after the class' constructor?

public class TestClass


{
public int TestProperty { get; set; } = 2;

public TestClass()
{
if (TestProperty == 1)

INFOBYTE CAREER INSTITUTE 158


{
Console.WriteLine("Shall this be executed?");
}

if (TestProperty == 2)
{
Console.WriteLine("Or shall this be executed");
}
}
}

var testInstance = new TestClass() { TestProperty = 1 };

In the example above, shall the TestProperty value be 1 in the class' constructor or after the class constructor?

Assigning property values in the instance creation like this:

var testInstance = new TestClass() {TestProperty = 1};

Will be executed after the constructor is run. However, initializing the property value in the class' property in C# 6.0 like
this:

public class TestClass


{
public int TestProperty { get; set; } = 2;

public TestClass()
{
}
}

will be done before the constructor is run.

Combining the two concepts above in a single example:

public class TestClass


{
public int TestProperty { get; set; } = 2;

public TestClass()
{
if (TestProperty == 1)
{
Console.WriteLine("Shall this be executed?");
}

if (TestProperty == 2)
{
Console.WriteLine("Or shall this be executed");
}
}
}

static void Main(string[] args)


{
var testInstance = new TestClass() { TestProperty = 1 };
Console.WriteLine(testInstance.TestProperty); //resulting in 1
}

INFOBYTE CAREER INSTITUTE 159


Final result:

"Or shall this be executed"


"1"

Explanation:

The TestProperty value will first be assigned as 2, then the TestClass constructor will be run, resulting in printing of

"Or shall this be executed"

And then the TestProperty will be assigned as 1 due to new TestClass() { TestProperty = 1 }, making the final value for the
TestProperty printed by Console.WriteLine(testInstance.TestProperty) to be

"1"

Section 39.10: Generic Static Constructors


If the type on which the static constructor is declared is generic, the static constructor will be called once for each
unique combination of generic arguments.

class Animal<T>
{
static Animal()
{
Console.WriteLine(typeof(T).FullName);
}

public static void Yawn() { }


}

Animal<Object>.Yawn();
Animal<String>.Yawn();

This will output:

System.Object
System.String

See also How do static constructors for generic types work ?

Section 39.11: Calling virtual methods in constructor


Unlike C++ in C# you can call a virtual method from class constructor (OK, you can also in C++ but behavior at first is
surprising). For example:

abstract class Base


{
protected Base()
{
_obj = CreateAnother();
}

INFOBYTE CAREER INSTITUTE 160


protected virtual AnotherBase CreateAnother()
{
return new AnotherBase();
}

private readonly AnotherBase _obj;


}

sealed class Derived : Base


{
public Derived() { }

protected override AnotherBase CreateAnother()


{
return new AnotherDerived();
}
}

var test = new Derived();


// test._obj is AnotherDerived

If you come from a C++ background this is surprising, base class constructor already sees derived class virtual
method table!

Be careful: derived class may not been fully initialized yet (its constructor will be executed after base class constructor)
and this technique is dangerous (there is also a StyleCop warning for this). Usually this is regarded as bad practice.

INFOBYTE CAREER INSTITUTE 161


Chapter 40: Access Modifiers
Section 40.1: Access Modifiers Diagrams
Here are all access modifiers in venn diagrams, from more limiting to more accessible:

Access Modifier Diagram

private

internal

protected

protected internal

INFOBYTE CAREER INSTITUTE 162


public

Below you could find more information.

Section 40.2: public


The public keyword makes a class (including nested classes), property, method or field available to every
consumer:

public class Foo()


{
public string SomeProperty { get; set; }

public class Baz


{
public int Value { get; set; }
}
}

public class Bar()


{
public Bar()
{
var myInstance = new Foo();
var someValue = foo.SomeProperty;
var myNestedInstance = new Foo.Baz();
var otherValue = myNestedInstance.Value;
}
}

Section 40.3: private


The private keyword marks properties, methods, fields and nested classes for use inside the class only:

public class Foo()


{
private string someProperty { get; set; }

private class Baz


{
public string Value { get; set; }
}

public void Do()


{
var baz = new Baz { Value = 42 };
}
}

INFOBYTE CAREER INSTITUTE 163


public class Bar()
{
public Bar()
{
var myInstance = new Foo();

Compile Error - not accessible due to private modifier var someValue =


foo.someProperty;
Compile Error - not accessible due to private modifier var baz = new
Foo.Baz();
}
}

Section 40.4: protected internal


The protected internal keyword marks field, methods, properties and nested classes for use inside the same assembly
or derived classes in another assembly:

Assembly 1

public class Foo


{
public string MyPublicProperty { get; set; }
protected internal string MyProtectedInternalProperty { get; set; }

protected internal class MyProtectedInternalNestedClass


{
private string blah;
public int N { get; set; }
}
}

public class Bar


{
void MyMethod1()
{
Foo foo = new Foo();
var myPublicProperty = foo.MyPublicProperty;
var myProtectedInternalProperty = foo.MyProtectedInternalProperty; var
myProtectedInternalNestedInstance =
new Foo.MyProtectedInternalNestedClass();
}
}

Assembly 2

public class Baz : Foo


{
void MyMethod1()
{
var myPublicProperty = MyPublicProperty;
var myProtectedInternalProperty = MyProtectedInternalProperty; var thing = new
MyProtectedInternalNestedClass();
}

void MyMethod2()

INFOBYTE CAREER INSTITUTE 164


{
Foo foo = new Foo();
var myPublicProperty = foo.MyPublicProperty;

// Compile Error
var myProtectedInternalProperty = foo.MyProtectedInternalProperty; // Compile Error

var myProtectedInternalNestedInstance =
new Foo.MyProtectedInternalNestedClass();
}

public class Qux


{
void MyMethod1()
{
Baz baz = new Baz();
var myPublicProperty = baz.MyPublicProperty;

// Compile Error
var myProtectedInternalProperty = baz.MyProtectedInternalProperty; // Compile Error

var myProtectedInternalNestedInstance =
new Baz.MyProtectedInternalNestedClass();
}

void MyMethod2()
{
Foo foo = new Foo();
var myPublicProperty = foo.MyPublicProperty;

//Compile Error
var myProtectedInternalProperty = foo.MyProtectedInternalProperty; // Compile Error

var myProtectedInternalNestedInstance =
new Foo.MyProtectedInternalNestedClass();
}
}

Section 40.5: internal


The internal keyword makes a class (including nested classes), property, method or field available to every
consumer in the same assembly:

internal class Foo


{
internal string SomeProperty {get; set;}
}

internal class Bar


{
var myInstance = new Foo();
internal string SomeField = foo.SomeProperty;

internal class Baz


{
private string blah;
public int N { get; set; }
}

INFOBYTE CAREER INSTITUTE 165


}

This can be broken to allow a testing assembly to access the code via adding code to AssemblyInfo.cs file:

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("MyTests")]

Section 40.6: protected


The protected keyword marks field, methods properties and nested classes for use inside the same class and
derived classes only:

public class Foo()


{
protected void SomeFooMethod()
{
//do something
}

protected class Thing


{
private string blah;
public int N { get; set; }
}
}

public class Bar() : Foo


{
private void someBarMethod()
{
SomeFooMethod(); // inside derived class
var thing = new Thing(); // can use nested class
}
}

public class Baz()


{
private void someBazMethod()
{
var foo = new Foo();
foo.SomeFooMethod(); //not accessible due to protected modifier
}
}

INFOBYTE CAREER INSTITUTE 166


Chapter 41: Interfaces
Section 41.1: Implementing an interface
An interface is used to enforce the presence of a method in any class that 'implements' it. The interface is defined with
the keyword interface and a class can 'implement' it by adding : InterfaceName after the class name. A class can implement
multiple interfaces by separating each interface with a comma.
InterfaceName, ISecondInterface

public interface INoiseMaker


{
string MakeNoise();
}

public class Cat : INoiseMaker


{
public string MakeNoise()
{
return "Nyan";
}
}

public class Dog : INoiseMaker


{
public string MakeNoise()
{
return "Woof";
}
}

Because they implement INoiseMaker, both cat and dog are required to include the string MakeNoise() method and will fail
to compile without it.

Section 41.2: Explicit interface implementation


Explicit interface implementation is necessary when you implement multiple interfaces who define a common method, but
different implementations are required depending on which interface is being used to call the method (note that you don't
need explicit implementations if multiple interfaces share the same method and a common implementation is possible).

interface IChauffeur
{
string Drive();
}

interface IGolfPlayer
{
string Drive();
}

class GolfingChauffeur : IChauffeur, IGolfPlayer


{
public string Drive()
{
return "Vroom!";
}

INFOBYTE CAREER INSTITUTE 167


string IGolfPlayer.Drive()
{
return "Took a swing...";
}
}

GolfingChauffeur obj = new GolfingChauffeur();


IChauffeur chauffeur = obj;
IGolfPlayer golfer = obj;

Console.WriteLine(obj.Drive()); // Vroom!
Console.WriteLine(chauffeur.Drive()); // Vroom!
Console.WriteLine(golfer.Drive()); // Took a swing...

The implementation cannot be called from anywhere else except by using the interface:

public class Golfer : IGolfPlayer


{
string IGolfPlayer.Drive()
{
return "Swinging hard...";
}
public void Swing()
{
Drive(); // Compiler error: No such method
}
}

Due to this, it may be advantageous to put complex implementation code of an explicitly implemented interface in a
separate, private method.

An explicit interface implementation can of course only be used for methods that actually exist for that interface:

public class ProGolfer : IGolfPlayer


{
string IGolfPlayer.Swear() // Error
{
return "The ball is in the pit";
}
}

Similarly, using an explicit interface implementation without declaring that interface on the class causes an error, too.

Hint:

Implementing interfaces explicitly can also be used to avoid dead code. When a method is no longer needed and gets
removed from the interface, the compiler will complain about each still existing implementation.

Note:

Programmers expect the contract to be the same regardless of the context of the type and explicit implementation
should not expose different behavior when called. So unlike the example above, IGolfPlayer.Drive and Drive should do the
same thing when possible.

INFOBYTE CAREER INSTITUTE 168


Section 41.3: Interface Basics
An Interface's function known as a "contract" of functionality. It means that it declares properties and methods but it
doesn't implement them.

So unlike classes Interfaces:

Can't be instantiated
Can't have any functionality
Can only contain methods * (Properties and Events are methods internally)
Inheriting an interface is called "Implementing"
You can inherit from 1 class, but you can "Implement" multiple Interfaces

public interface ICanDoThis{


void TheThingICanDo();
int SomeValueProperty { get; set; }
}

Things to notice:

The "I" prefix is a naming convention used for interfaces.


The function body is replaced with a semicolon ";".
Properties are also allowed because internally they are also methods

public class MyClass : ICanDoThis {


public void TheThingICanDo(){
// do the thing
}

public int SomeValueProperty { get; set; }


public int SomeValueNotImplemtingAnything { get; set; }
}

ICanDoThis obj = new MyClass();

// ok
obj.TheThingICanDo();

// ok
obj.SomeValueProperty = 5;

Error, this member doesn't exist in the interface


obj.SomeValueNotImplemtingAnything = 5;

in order to access the property in the class you must "down cast" it
((MyClass)obj).SomeValueNotImplemtingAnything = 5; // ok

This is especially useful when you're working with UI frameworks such as WinForms or WPF because it's mandatory to
inherit from a base class to create user control and you loose the ability to create abstraction over different control types.
An example? Coming up:

public class MyTextBlock : TextBlock {


public void SetText(string str){
this.Text = str;
}

INFOBYTE CAREER INSTITUTE 169


}

public class MyButton : Button {


public void SetText(string str){
this.Content = str;
}
}

The problem proposed is that both contain some concept of "Text" but the property names differ. And you can't create
create a abstract base class because they have a mandatory inheritance to 2 different classes. An interface can
alleviate that

public interface ITextControl{


void SetText(string str);
}

public class MyTextBlock : TextBlock, ITextControl { public void


SetText(string str){
this.Text = str;
}
}

public class MyButton : Button, ITextControl {


public void SetText(string str){
this.Content = str;
}

public int Clicks { get; set; }


}

Now MyButton and MyTextBlock is interchangeable.

var controls = new List<ITextControls>{


new MyTextBlock(),
new MyButton()
};

foreach(var ctrl in controls){


ctrl.SetText("This text will be applied to both controls despite them being different");

Compiler Error, no such member in interface ctrl.Clicks =


0;

Runtime Error because 1 class is in fact not a button which makes this cast invalid ((MyButton)ctrl).Clicks = 0;

/* the solution is to check the type first.


This is usually considered bad practice since
it's a symptom of poor abstraction */
var button = ctrl as MyButton;
if(button != null)
button.Clicks = 0; // no errors

INFOBYTE CAREER INSTITUTE 170


Section 41.4: IComparable<T> as an Example of Implementing
an Interface
Interfaces can seem abstract until you seem them in practice. The IComparable and IComparable<T> are great
examples of why interfaces can be helpful to us.

Let's say that in a program for a online store, we have a variety of items you can buy. Each item has a name, an ID
number, and a price.

public class Item {

public string name; // though public variables are generally bad practice, public int idNumber; // to
keep this example simple we will use them instead public decimal price; // of a property.

// body omitted for brevity

We have our Items stored inside of a List<Item>, and in our program somewhere, we want to sort our list by ID number
from smallest to largest. Instead of writing our own sorting algorithm, we can instead use the Sort() method that
List<T> already has. However, as our Item class is right now, there is no way for the List<T> to understand what order
to sort the list. Here is where the IComparable interface comes in.

To correctly implement the CompareTo method, CompareTo should return a positive number if the parameter is "less than"
the current one, zero if they are equal, and a negative number if the parameter is "greater than".

Item apple = new Item();


apple.idNumber = 15;
Item banana = new Item();
banana.idNumber = 4;
Item cow = new Item();
cow.idNumber = 15;
Item diamond = new Item();
diamond.idNumber = 18;

Console.WriteLine(apple.CompareTo(banana)); // 11
Console.WriteLine(apple.CompareTo(cow)); // 0
Console.WriteLine(apple.CompareTo(diamond)); // -3

Here's the example Item's implementation of the interface:

public class Item : IComparable<Item> {

private string name;


private int idNumber;
private decimal price;

public int CompareTo(Item otherItem) {

return (this.idNumber - otherItem.idNumber);

// rest of code omitted for brevity

INFOBYTE CAREER INSTITUTE 171


On a surface level, the CompareTo method in our item simply returns the difference in their ID numbers, but what does
the above do in practice?

Now, when we call Sort() on a List<Item> object, the List will automatically call the Item's CompareTo method when it
needs to determine what order to put objects in. Furthermore, besides List<T>, any other objects that need the ability
to compare two objects will work with the Item because we have defined the ability for two different Items to be
compared with one another.

Section 41.5: Implementing multiple interfaces


public interface IAnimal
{
string Name { get; set; }
}

public interface INoiseMaker


{
string MakeNoise();
}

public class Cat : IAnimal, INoiseMaker


{
public Cat()
{
Name = "Cat";
}

public string Name { get; set; }

public string MakeNoise()


{
return "Nyan";
}
}

Section 41.6: Why we use interfaces


An interface is a definition of a contract between the user of the interface and the class that implement it. One way to
think of an interface is as a declaration that an object can perform certain functions.

Let's say that we define an interface IShape to represent different type of shapes, we expect a shape to have an area,
so we will define a method to force the interface implementations to return their area :

public interface IShape


{
double ComputeArea();
}

Let's that we have the following two shapes : a Rectangle and a Circle

public class Rectangle : IShape


{
private double length;
private double width;

public Rectangle(double length, double width)


{
this.length = length;

INFOBYTE CAREER INSTITUTE 172


this.width = width;
}

public double ComputeArea()


{
return length * width;
}
}

public class Circle : IShape


{
private double radius;

public Circle(double radius)


{
this.radius = radius;
}

public double ComputeArea()


{
return Math.Pow(radius, 2.0) * Math.PI;
}
}

Each one of them have its own definition of its area, but both of them are shapes. So it's only logical to see them as
IShape in our program :

private static void Main(string[] args)


{
var shapes = new List<IShape>() { new Rectangle(5, 10), new Circle(5) }; ComputeArea(shapes);

Console.ReadKey();
}

private static void ComputeArea(IEnumerable<IShape> shapes)


{
foreach (shape in shapes)
{
Console.WriteLine("Area: {0:N}, shape.ComputeArea());
}
}

Output:
Area : 50.00
Area : 78.54

Section 41.7: "Hiding" members with Explicit Implementation


Don't you hate it when interfaces pollute you class with too many members you don't even care about? Well I got a
solution! Explicit Implementations

public interface IMessageService {


void OnMessageRecieve();
void SendMessage();
string Result { get; set; }
int Encoding { get; set; }
// yadda yadda
}

INFOBYTE CAREER INSTITUTE 173


Normally you'd implement the class like this.

public class MyObjectWithMessages : IMessageService { public void


OnMessageRecieve(){

public void SendMessage(){

public string Result { get; set; }


public int Encoding { get; set; }
}

Every member is public.

var obj = new MyObjectWithMessages();

why would i want to call this function?


obj.OnMessageRecieve();

Answer: I don't. So neither should it be declared public but simply declaring the members as private will make the
compiler throw an error

The solution is to use explicit implementation:

public class MyObjectWithMessages : IMessageService{ void


IMessageService.OnMessageRecieve() {

void IMessageService.SendMessage() {

string IMessageService.Result { get; set; }


int IMessageService.Encoding { get; set; }
}

So now you have implemented the members as required and they won't expose any members in as public.

var obj = new MyObjectWithMessages();

/* error member does not exist on type MyObjectWithMessages.


We've succesfully made it "private" */
obj.OnMessageRecieve();

If you seriously still want to access the member even though is explicitly implement all you have to do is cast the
object to the interface and you good to go.

((IMessageService)obj).OnMessageRecieve();

INFOBYTE CAREER INSTITUTE 174


Chapter 42: Static Classes
Section 42.1: Static Classes
The "static" keyword when referring to a class has three effects:

You cannot create an instance of a static class (this even removes the default constructor)
All properties and methods in the class must be static as well.
A static class is a sealed class, meaning it cannot be inherited.

public static class Foo


{
//Notice there is no constructor as this cannot be an instance public static int
Counter { get; set; } public static int GetCount()

{
return Counter;
}
}

public class Program


{
static void Main(string[] args)
{
Foo.Counter++;
Console.WriteLine(Foo.GetCount()); //this will print 1

//var foo1 = new Foo();


//this line would break the code as the Foo class does not have a constructor
}
}

Section 42.2: Static class lifetime


A static class is lazily initialized on member access and lives for the duration of the application domain.

void Main()
{
Console.WriteLine("Static classes are lazily initialized");
Console.WriteLine("The static constructor is only invoked when the class is first accessed"); Foo.SayHi();

Console.WriteLine("Reflecting on a type won't trigger its static .ctor"); var barType = typeof(Bar);

Console.WriteLine("However, you can manually trigger it with


System.Runtime.CompilerServices.RuntimeHelpers");
RuntimeHelpers.RunClassConstructor(barType.TypeHandle);
}

Define other methods and classes here public


static class Foo
{
static Foo()
{
Console.WriteLine("static Foo.ctor");
}
public static void SayHi()

INFOBYTE CAREER INSTITUTE 175


{
Console.WriteLine("Foo: Hi");
}
}
public static class Bar
{
static Bar()
{
Console.WriteLine("static Bar.ctor");
}
}

Section 42.3: Static keyword


The static keyword means 2 things:

This value does not change from object to object but rather changes on a class as a whole
Static properties and methods don't require an instance.

public class Foo


{
public Foo{
Counter++;
NonStaticCounter++;
}

public static int Counter { get; set; }


public int NonStaticCounter { get; set; }
}

public class Program


{
static void Main(string[] args)
{
//Create an instance
var foo1 = new Foo();
Console.WriteLine(foo1.NonStaticCounter); //this will print "1"

//Notice this next call doesn't access the instance but calls by the class name.
Console.WriteLine(Foo.Counter); //this will also print "1"

//Create a second instance


var foo2 = new Foo();

Console.WriteLine(foo2.NonStaticCounter); //this will print "1"

Console.WriteLine(Foo.Counter); //this will now print "2"


//The static property incremented on both instances and can persist for the whole class

}
}

INFOBYTE CAREER INSTITUTE 176


Chapter 43: Singleton Implementation
Section 43.1: Statically Initialized Singleton
public class Singleton
{
private readonly static Singleton instance = new Singleton(); private Singleton() { }

public static Singleton Instance => instance;


}

This implementation is thread-safe because in this case instance object is initialized in the static constructor. The CLR
already ensures that all static constructors are executed thread-safe.

Mutating instance is not a thread-safe operation, therefore the readonly attribute guarantees immutability after
initialization.

Section 43.2: Lazy, thread-safe Singleton (using Lazy<T>)


.Net 4.0 type Lazy guarantees thread-safe object initialization, so this type could be used to make Singletons.

public class LazySingleton


{
private static readonly Lazy<LazySingleton> _instance = new
Lazy<LazySingleton>(() => new LazySingleton());

public static LazySingleton Instance


{
get { return _instance.Value; }
}

private LazySingleton() { }
}

Using Lazy<T> will make sure that the object is only instantiated when it is used somewhere in the calling code.

A simple usage will be like:

using System;

public class Program


{
public static void Main()
{
var instance = LazySingleton.Instance;
}
}

Live Demo on .NET Fiddle

Section 43.3: Lazy, thread-safe Singleton (using Double


Checked Locking)
This thread-safe version of a singleton was necessary in the early versions of .NET where static initialization was not
guaranteed to be thread-safe. In more modern versions of the framework a statically initialized singleton is

INFOBYTE CAREER INSTITUTE 177


usually preferred because it is very easy to make implementation mistakes in the following pattern.

public sealed class ThreadSafeSingleton


{
private static volatile ThreadSafeSingleton instance; private static object
lockObject = new Object();

private ThreadSafeSingleton()
{
}

public static ThreadSafeSingleton Instance


{
get
{
if (instance == null)
{
lock (lockObject)
{
if (instance == null)
{
instance = new ThreadSafeSingleton();
}
}
}

return instance;
}
}
}

Notice that the if (instance == null) check is done twice: once before the lock is acquired, and once afterwards. This
implementation would still be thread-safe even without the first null check. However, that would mean that a lock would
be acquired every time the instance is requested, and that would cause performance to suffer. The first null check is
added so that the lock is not acquired unless it's necessary. The second null check makes sure that only the first thread
to acquire the lock then creates the instance. The other threads will find the instance to be populated and skip ahead.

Section 43.4: Lazy, thread safe singleton (for .NET 3.5 or


older, alternate implementation)
Because in .NET 3.5 and older you don't have Lazy<T> class you use the following pattern:

public class Singleton


{
private Singleton() // prevents public instantiation
{
}

public static Singleton Instance


{
get
{
return Nested.instance;
}
}

private class Nested


{

INFOBYTE CAREER INSTITUTE 178


Explicit static constructor to tell C# compiler
not to mark type as beforefieldinit
static Nested()
{
}

internal static readonly Singleton instance = new Singleton();


}
}

This is inspired from Jon Skeet's blog post.

Because the Nested class is nested and private the instantiation of the singleton instance will not be triggered by
accessing other members of the Sigleton class (such as a public readonly property, for example).

INFOBYTE CAREER INSTITUTE 179


Chapter 44: Dependency Injection
Section 44.1: Dependency Injection C# and ASP.NET with Unity
First why we should use depedency injection in our code ? We want to decouple other components from other
classes in our program. For example we have class AnimalController which have code like this :

public class AnimalController()


{
private SantaAndHisReindeer _SantaAndHisReindeer = new SantaAndHisReindeer();

public AnimalController(){
Console.WriteLine("");
}
}

We look at this code and we think everything is ok but now our AnimalController is reliant on object
_SantaAndHisReindeer. Automatically my Controller is bad to testing and reusability of my code will be very hard.

Very good explanation why we should use Depedency Injection and interfaces here.

If we want Unity to handle DI, the road to achieve this is very simple :) With NuGet( package manager) we can easily
import unity to our code.

in Visual Studio Tools -> NuGet Package Manager -> Manage Packages for Solution -> in search input write
unity -> choose our project-> click install

Now two files with nice comments will be created.

in App-Data folder UnityConfig.cs and UnityMvcActivator.cs

UnityConfig - in RegisterTypes method, we can see type that will be injection in our constructors.

namespace Vegan.WebUi.App_Start
{

public class UnityConfig


{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});

<summary>
Gets the configured Unity container.
</summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;

INFOBYTE CAREER INSTITUTE 180


}
#endregion

<summary>Registers the type mappings with the Unity container.</summary>


<param name="container">The unity container to configure.</param>
<remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to

change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>

public static void RegisterTypes(IUnityContainer container)


{
NOTE: To load from web.config uncomment the line below. Make sure to add a
Microsoft.Practices.Unity.Configuration to the using statements.
container.LoadConfiguration();

TODO: Register your types here


container.RegisterType<IProductRepository, ProductRepository>();

container.RegisterType<ISanta, SantaAndHisReindeer>();

}
}
}

UnityMvcActivator - > also with nice comments which say that this class integrates Unity with ASP.NET
MVC

using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;

[assembly:
WebActivatorEx.PreApplicationStartMethod(typeof(Vegan.WebUi.App_Start.UnityWebActivator), "Start")]
[assembly:
WebActivatorEx.ApplicationShutdownMethod(typeof(Vegan.WebUi.App_Start.UnityWebActivator),
"Shutdown")]

namespace Vegan.WebUi.App_Start
{
<summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary> public static class
UnityWebActivator
{
<summary>Integrates Unity when the application starts.</summary> public static
void Start()
{
var container = UnityConfig.GetConfiguredContainer();

FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().
First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

TODO: Uncomment if you want to use PerRequestLifetimeManager

Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerR equestHttpModule));

INFOBYTE CAREER INSTITUTE 181


<summary>Disposes the Unity container when the application is shut down.</summary> public static void
Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}

Now we can decouple our Controller from class SantAndHisReindeer :)

public class AnimalController()


{
private readonly SantaAndHisReindeer _SantaAndHisReindeer;

public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){

_SantAndHisReindeer = SantaAndHisReindeer;
}
}

There is one final thing we must do before running our application.

In Global.asax.cs we must add new line: UnityWebActivator.Start() which will start, configure Unity and register our
types.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Vegan.WebUi.App_Start;

namespace Vegan.WebUi
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
UnityWebActivator.Start();
}
}
}

Section 44.2: Dependency injection using MEF


public interface ILogger
{
void Log(string message);
}

[Export(typeof(ILogger))]

INFOBYTE CAREER INSTITUTE 182


[ExportMetadata("Name", "Console")]
public class ConsoleLogger:ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}

[Export(typeof(ILogger))]
[ExportMetadata("Name", "File")]
public class FileLogger:ILogger
{
public void Log(string message)
{
//Write the message to file
}
}

public class User


{
private readonly ILogger logger;
public User(ILogger logger)
{
this.logger = logger;
}
public void LogUser(string message)
{
logger.Log(message) ;
}
}

public interface ILoggerMetaData


{
string Name { get; }
}

internal class Program


{
private CompositionContainer _container;

[ImportMany]
private IEnumerable<Lazy<ILogger, ILoggerMetaData>> _loggers;

private static void Main()


{
ComposeLoggers();
Lazy<ILogger, ILoggerMetaData> loggerNameAndLoggerMapping = _ loggers.First((n) =>
((n.Metadata.Name.ToUpper() =="Console"));
ILogger logger= loggerNameAndLoggerMapping.Value
var user = new User(logger);
user.LogUser("user name");
}

private void ComposeLoggers()


{
//An aggregate catalog that combines multiple catalogs var catalog =
new AggregateCatalog();
string loggersDllDirectory =Path.Combine(Utilities.GetApplicationDirectory(), "Loggers");
if (!Directory.Exists(loggersDllDirectory ))
{
Directory.CreateDirectory(loggersDllDirectory );

INFOBYTE CAREER INSTITUTE 183


}
//Adds all the parts found in the same assembly as the PluginManager class
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
catalog.Catalogs.Add(new DirectoryCatalog(loggersDllDirectory ));

//Create the CompositionContainer with the parts in the catalog _container = new
CompositionContainer(catalog);

//Fill the imports of this object


try
{
this._container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
throw new CompositionException(compositionException.Message);
}
}
}

INFOBYTE CAREER INSTITUTE 184


Chapter 45: Partial class and methods
Partial classes provides us an option to split classes into multiple parts and in multiple source files. All parts are
combined into one single class during compile time. All parts should contain the keyword partial,should be of the same
accessibility. All parts should be present in the same assembly for it to be included during compile time.

Section 45.1: Partial classes


Partial classes provide an ability to split class declaration (usually into separate files). A common problem that can be
solved with partial classes is allowing users to modify auto-generated code without fearing that their changes will be
overwritten if the code is regenerated. Also multiple developers can work on same class or methods.

using System;

namespace PartialClassAndMethods
{
public partial class PartialClass
{
public void ExampleMethod() {
Console.WriteLine("Method call from the first declaration.");
}
}

public partial class PartialClass


{
public void AnotherExampleMethod()
{
Console.WriteLine("Method call from the second declaration.");
}
}

class Program
{
static void Main(string[] args)
{
PartialClass partial = new PartialClass();
partial.ExampleMethod(); // outputs "Method call from the first declaration."
partial.AnotherExampleMethod(); // outputs "Method call from the second declaration."
}
}
}

Section 45.2: Partial classes inheriting from a base class


When inheriting from any base class, only one partial class needs to have the base class specified.

// PartialClass1.cs
public partial class PartialClass : BaseClass {}

// PartialClass2.cs
public partial class PartialClass {}

You can specify the same base class in more than one partial class. It will get flagged as redundant by some IDE
tools, but it does compile correctly.

// PartialClass1.cs
public partial class PartialClass : BaseClass {}

INFOBYTE CAREER INSTITUTE 185


// PartialClass2.cs
public partial class PartialClass : BaseClass {} // base class here is redundant

You cannot specify different base classes in multiple partial classes, it will result in a compiler error.

// PartialClass1.cs
public partial class PartialClass : BaseClass {} // compiler error

// PartialClass2.cs
public partial class PartialClass : OtherBaseClass {} // compiler error

Section 45.3: Partial methods


Partial method consists of the definition in one partial class declaration (as a common scenario - in the auto-
generated one) and the implementation in another partial class declaration.

using System;

namespace PartialClassAndMethods
{
public partial class PartialClass // Auto-generated
{
partial void PartialMethod();
}

public partial class PartialClass // Human-written


{
public void PartialMethod()
{
Console.WriteLine("Partial method called.");
}
}

class Program
{
static void Main(string[] args)
{
PartialClass partial = new PartialClass();
partial.PartialMethod(); // outputs "Partial method called."
}
}
}

INFOBYTE CAREER INSTITUTE 186


Chapter 46: Object initializers
Section 46.1: Simple usage
Object initializers are handy when you need to create an object and set a couple of properties right away, but the
available constructors are not sufficient. Say you have a class

public class Book


{
public string Title { get; set; }
public string Author { get; set; }

// the rest of class definition


}

To initialize a new instance of the class with an initializer:

Book theBook = new Book { Title = "Don Quixote", Author = "Miguel de Cervantes" };

This is equivalent to

Book theBook = new Book();


theBook.Title = "Don Quixote";
theBook.Author = "Miguel de Cervantes";

Section 46.2: Usage with non-default constructors


You can combine object initializers with constructors to initialize types if necessary. Take for example a class
defined as such:

public class Book {


public string Title { get; set; }
public string Author { get; set; }

public Book(int id) {


//do things
}

// the rest of class definition


}

var someBook = new Book(16) { Title = "Don Quixote", Author = "Miguel de Cervantes" }

This will first instantiate a Book with the Book(int) constructor, then set each property in the initializer. It is
equivalent to:

var someBook = new Book(16);


someBook.Title = "Don Quixote";
someBook.Author = "Miguel de Cervantes";

Section 46.3: Usage with anonymous types


Object initializers are the only way to initialize anonymous types, which are types generated by the compiler.

var album = new { Band = "Beatles", Title = "Abbey Road" };

INFOBYTE CAREER INSTITUTE 187


For that reason object initializers are widely used in LINQ select queries, since they provide a convenient way to
specify which parts of a queried object you are interested in.

var albumTitles = from a in albums


select new
{
Title = a.Title,
Artist = a.Band
};

INFOBYTE CAREER INSTITUTE 188


Chapter 47: Methods
Section 47.1: Calling a Method
Calling a static method:

// Single argument
System.Console.WriteLine("Hello World");

Multiple arguments
string name = "User";
System.Console.WriteLine("Hello, {0}!", name);

Calling a static method and storing its return value:

string input = System.Console.ReadLine();

Calling an instance method:

int x = 42;
The instance method called here is Int32.ToString() string xAsString
= x.ToString();

Calling a generic method

Assuming a method 'T[] CreateArray<T>(int size)' DateTime[]


dates = CreateArray<DateTime>(8);

Section 47.2: Anonymous method


Anonymous methods provide a technique to pass a code block as a delegate parameter. They are methods with a
body, but no name.

delegate int IntOp(int lhs, int rhs);

class Program
{
static void Main(string[] args)
{
// C# 2.0 definition
IntOp add = delegate(int lhs, int rhs)
{
return lhs + rhs;
};

C# 3.0 definition IntOp mul =


(lhs, rhs) =>
{
return lhs * rhs;
};

C# 3.0 definition - shorthand IntOp sub =


(lhs, rhs) => lhs - rhs;

Calling each method


Console.WriteLine("2 + 3 = " + add(2, 3));
Console.WriteLine("2 * 3 = " + mul(2, 3));

INFOBYTE CAREER INSTITUTE 189


Console.WriteLine("2 - 3 = " + sub(2, 3));
}
}

Section 47.3: Declaring a Method


Every method has a unique signature consisting of a accessor ( public, private, ...) ,optional modifier (abstract), a name
and if needed method parameters. Note, that the return type is not part of the signature. A method prototype looks like
the following:

AccessModifier OptionalModifier ReturnType MethodName(InputParameters)


{
//Method body
}

AccessModifier can be public, protected, pirvate or by default internal.

OptionalModifier can be static abstract virtual override new or sealed.

ReturnType can be void for no return or can be any type from the basic ones, as int to complex classes.

a Method may have some or no input parameters. to set parameters for a method, you should declare each one like
normal variable declarations (like int a), and for more than one parameter you should use comma between them (like
int a, int b).

Parameters may have default values. for this you should set a value for the parameter (like int a = 0). if a
parameter has a default value, setting the input value is optional.

The following method example returns the sum of two integers:

private int Sum(int a, int b)


{
return a + b;
}

Section 47.4: Parameters and Arguments


A method can declare any number of parameters (in this example, i, s and o are the parameters):

static void DoSomething(int i, string s, object o) {


Console.WriteLine(String.Format("i={0}, s={1}, o={2}", i, s, o));
}

Parameters can be used to pass values into a method, so that the method can work with them. This can be every kind
of work like printing the values, or making modifications to the object referenced by a parameter, or storing the values.

When you call the method, you need to pass an actual value for every parameter. At this point, the values that you
actually pass to the method call are called Arguments:

DoSomething(x, "hello", new object());

Section 47.5: Return Types


A method can return either nothing (void), or a value of a specified type:

INFOBYTE CAREER INSTITUTE 190


If you don't want to return a value, use void as return type. static void
ReturnsNothing() {
Console.WriteLine("Returns nothing");
}

If you want to return a value, you need to specify its type. static string
ReturnsHelloWorld() {
return "Hello World";
}

If your method specifies a return value, the method must return a value. You do this using the return statement. Once a
return statement has been reached, it returns the specified value and any code after it will not be run anymore
(exceptions are finally blocks, which will still be executed before the method returns).

If your method returns nothing (void), you can still use the return statement without a value if you want to return from the
method immediately. At the end of such a method, a return statement would be unnecessary though.

Examples of valid return statements:

return;
return 0;
return x * 2;
return Console.ReadLine();

Throwing an exception can end method execution without returning a value. Also, there are iterator blocks, where return
values are generated by using the yield keyword, but those are special cases that will not be explained at this point.

Section 47.6: Default Parameters


You can use default parameters if you want to provide the option to leave out parameters:

static void SaySomething(string what = "ehh") {


Console.WriteLine(what);
}

static void Main() {


prints "hello"
SaySomething("hello");
prints "ehh"
SaySomething(); // The compiler compiles this as if we had typed SaySomething("ehh")
}

When you call such a method and omit a parameter for which a default value is provided, the compiler inserts that
default value for you.

Keep in mind that parameters with default values need to be written after parameters without default values.

static void SaySomething(string say, string what = "ehh") { //Correct

Console.WriteLine(say + what);
}

static void SaySomethingElse(string what = "ehh", string say) { //Incorrect

Console.WriteLine(say + what);
}

INFOBYTE CAREER INSTITUTE 191


WARNING: Because it works that way, default values can be problematic in some cases. If you change the default
value of a method parameter and don't recompile all callers of that method, those callers will still use the default value
that was present when they were compiled, possibly causing inconsistencies.

Section 47.7: Method overloading


Definition : When multiple methods with the same name are declared with different parameters, it is referred to as
method overloading. Method overloading typically represents functions that are identical in their purpose but are written to
accept different data types as their parameters.

Factors affecting

Number of Arguments
Type of arguments
Return Type**

Consider a method named Area that will perform calculation functions, which will accepts various arguments and return
the result.

Example

public string Area(int value1)


{
return String.Format("Area of Square is {0}", value1 * value1);
}

This method will accepts one argument and return a string, if we call the method with an integer(say 5) the output will
be "Area of Square is 25".

public double Area(double value1, double value2)


{
return value1 * value2;
}

Similarly if we pass two double values to this method the output will be the product of the two values and are of type
double. This can be used of multiplication as well as finding the Area of rectangles

public double Area(double value1)


{
return 3.14 * Math.Pow(value1,2);
}

This can be used specially for finding the area of circle, which will accepts a double value( radius) and return
another double value as its Area.

Each of these methods can be called normally without conflict - the compiler will examine the parameters of each
method call to determine which version of Area needs to be used.

string squareArea = Area(2);


double rectangleArea = Area(32.0, 17.5);
double circleArea = Area(5.0); // all of these are valid and will compile.

**Note that return type alone cannot differentiate between two methods. For instance, if we had two definitions for
Area that had the same parameters, like so:

INFOBYTE CAREER INSTITUTE 192


public string Area(double width, double height) { ... } public double
Area(double width, double height) { ... } // This will NOT compile.

If we need to have our class use the same method names that return different values, we can remove the issues of
ambiguity by implementing an interface and explicitly defining its usage.

public interface IAreaCalculatorString {

public string Area(double width, double height);

public class AreaCalculator : IAreaCalculatorString {

public string IAreaCalculatorString.Area(double width, double height) { ... }


Note that the method call now explicitly says it will be used when called through
the IAreaCalculatorString interface, allowing us to resolve the ambiguity. public double
Area(double width, double height) { ... }

Section 47.8: Access rights


static: is callable on a class even when no instance of the class has been created public static void
MyMethod()

virtual: can be called or overridden in an inherited class


public virtual void MyMethod()

internal: access is limited within the current assembly internal void


MyMethod()

//private: access is limited only within the same class private void
MyMethod()

//public: access right from every class / assembly


public void MyMethod()

//protected: access is limited to the containing class or types derived from it protected void MyMethod()

//protected internal: access is limited to the current assembly or types derived from the containing class.

protected internal void MyMethod()

INFOBYTE CAREER INSTITUTE 193


Chapter 48: Extension Methods
Parameter Details
The first parameter of an extension method should always be preceded by the this keyword, followed
this
by the identifier with which to refer to the "current" instance of the object you are extending

Section 48.1: Extension methods - overview


Extension methods were introduced in C# 3.0. Extension methods extend and add behavior to existing types without
creating a new derived type, recompiling, or otherwise modifying the original type. They are especially helpful when you
cannot modify the source of a type you are looking to enhance. Extension methods may be created for system types,
types defined by third parties, and types that you have defined yourself. The extension method can be invoked as though
it were a member method of the original type. This allows for Method Chaining used to implement a Fluent Interface.

An extension method is created by adding a static method to a static class which is distinct from the original type being
extended. The static class holding the extension method is often created for the sole purpose of holding extension
methods.

Extension methods take a special first parameter that designates the original type being extended. This first parameter is
decorated with the keyword this (which constitutes a special and distinct use of this in C#—it should be understood as
different from the use of this which allows referring to members of the current object instance).

In the following example, the original type being extended is the class string. String has been extended by a method
Shorten(), which provides the additional functionality of shortening. The static class StringExtensions has been created to
hold the extension method. The extension method Shorten() shows that it is an extension of string via the specially
marked first parameter. To show that the Shorten() method extends string, the first parameter is marked with this.
Therefore, the full signature of the first parameter is this string text, where string is the original type being extended and
text is the chosen parameter name.

static class StringExtensions


{
public static string Shorten(this string text, int length)
{
return text.Substring(0, length);
}
}

class Program
{
static void Main()
{
This calls method String.ToUpper() var myString
= "Hello World!".ToUpper();

This calls the extension method StringExtensions.Shorten() var newString =


myString.Shorten(5);

It is worth noting that the above call is purely syntactic sugar


and the assignment below is functionally equivalent
var newString2 = StringExtensions.Shorten(myString, 5);
}
}

Live Demo on .NET Fiddle

INFOBYTE CAREER INSTITUTE 194


The object passed as the first argument of an extension method (which is accompanied by the this keyword) is the
instance the extension method is called upon.

For example, when this code is executed:

"some string".Shorten(5);

The values of the arguments are as below:

text: "some string"


length: 5

Note that extension methods are only usable if they are in the same namespace as their definition, if the namespace
is imported explicitly by the code using the extension method, or if the extension class is namespace-less. The .NET
framework guidelines recommend putting extension classes in their own namespace. However, this may lead to
discovery issues.

This results in no conflicts between the extension methods and the libraries being used, unless namespaces which
might conflict are explicitly pulled in. For example LINQ Extensions:

using System.Linq; // Allows use of extension methods from the System.Linq namespace

class Program
{
static void Main()
{
var ints = new int[] {1, 2, 3, 4};

Call Where() extension method from the System.Linq namespace var even =
ints.Where(x => x % 2 == 0);
}
}

Live Demo on .NET Fiddle

Since C# 6.0, it is also possible to put a using static directive to the class containing the extension methods. For
example, using static System.Linq.Enumerable;. This makes extension methods from that particular class available
without bringing other types from the same namespace into scope.

When a class method with the same signature is available, the compiler prioritizes it over the extension method call.
For example:

class Test
{
public void Hello()
{
Console.WriteLine("From Test");
}
}

static class TestExtensions


{
public static void Hello(this Test test)
{
Console.WriteLine("From extension method");
}
}

INFOBYTE CAREER INSTITUTE 195


class Program
{
static void Main()
{
Test t = new Test();
t.Hello(); // Prints "From Test"
}
}

Live demo on .NET Fiddle

Note that if there are two extension functions with the same signature, and one of them is in the same namespace, then
that one will be prioritized. On the other hand, if both of them are accessed by using, then a compile time error will ensue
with the message:

The call is ambiguous between the following methods or properties

Note that the syntactic convenience of calling an extension method via originalTypeInstance.ExtensionMethod() is an
optional convenience. The method can also be called in the traditional manner, so that the special first parameter is used
as a parameter to the method.

I.e., both of the following work:

//Calling as though method belongs to string--it seamlessly extends string String s = "Hello World";

s.Shorten(5);

//Calling as a traditional static method with two parameters


StringExtensions.Shorten(s, 5);

Section 48.2: Null checking


Extension methods are static methods which behave like instance methods. However, unlike what happens when
calling an instance method on a null reference, when an extension method is called with a null reference, it does not
throw a NullReferenceException. This can be quite useful in some scenarios.

For example, consider the following static class:

public static class StringExtensions


{
public static string EmptyIfNull(this string text)
{
return text ?? String.Empty;
}

public static string NullIfEmpty(this string text)


{
return String.Empty == text ? null : text;
}
}

string nullString = null;


string emptyString = nullString.EmptyIfNull();// will return ""
string anotherNullString = emptyString.NullIfEmpty(); // will return null

Live Demo on .NET Fiddle

INFOBYTE CAREER INSTITUTE 196


Section 48.3: Explicitly using an extension method
Extension methods can also be used like ordinary static class methods. This way of calling an extension method is
more verbose, but is necessary in some cases.

static class StringExtensions


{
public static string Shorten(this string text, int length)
{
return text.Substring(0, length);
}
}

Usage:

var newString = StringExtensions.Shorten("Hello World", 5);


When to call extension methods as static methods

There are still scenarios where you would need to use an extension method as a static method:

Resolving conflict with a member method. This can happen if a new version of a library introduces a new
member method with the same signature. In this case, the member method will be preferred by the compiler.
Resolving conflicts with another extension method with the same signature. This can happen if two libraries
include similar extension methods and namespaces of both classes with extension methods are used in the
same file.
Passing extension method as a method group into delegate parameter.
Doing your own binding through Reflection.
Using the extension method in the Immediate window in Visual Studio.

Using static

If a using static directive is used to bring static members of a static class into global scope, extension methods are
skipped. Example:

using static OurNamespace.StringExtensions; // refers to class in previous example

OK: extension method syntax still works. "Hello


World".Shorten(5);
OK: static method syntax still works.
OurNamespace.StringExtensions.Shorten("Hello World", 5);
Compile time error: extension methods can't be called as static without specifying class. Shorten("Hello World", 5);

If you remove the this modifier from the first argument of the Shorten method, the last line will compile.

Section 48.4: Generic Extension Methods


Just like other methods, extension methods can use generics. For example:

static class Extensions


{
public static bool HasMoreThanThreeElements<T>(this IEnumerable<T> enumerable)
{
return enumerable.Take(4).Count() > 3;
}

INFOBYTE CAREER INSTITUTE 197


}

and calling it would be like:

IEnumerable<int> numbers = new List<int> {1,2,3,4,5,6};


var hasMoreThanThreeElements = numbers.HasMoreThanThreeElements();

View Demo

Likewise for multiple Type Arguments:

public static TU GenericExt<T, TU>(this T obj)


{
TU ret = default(TU);
do some stuff with obj return
ret;
}

Calling it would be like:

IEnumerable<int> numbers = new List<int> {1,2,3,4,5,6}; var result =


numbers.GenericExt<IEnumerable<int>,String>();

View Demo

You can also create extension methods for partially bound types in multi generic types:

class MyType<T1, T2>


{
}

static class Extensions


{
public static void Example<T>(this MyType<int, T> test)
{
}
}

Calling it would be like:

MyType<int, string> t = new MyType<int, string>(); t.Example();

View Demo

You can also specify type constraints with where :

public static bool IsDefault<T>(this T obj) where T : struct, IEquatable<T>


{
return EqualityComparer<T>.Default.Equals(obj, default(T));
}

Calling code:

int number = 5;
var IsDefault = number.IsDefault();

INFOBYTE CAREER INSTITUTE 198


View Demo

Section 48.5: Extension methods can only see public


(or internal) members of the extended class
public class SomeClass
{
public void DoStuff()
{

protected void DoMagic()


{

}
}

public static class SomeClassExtensions


{
public static void DoStuffWrapper(this SomeClass someInstance)
{
someInstance.DoStuff(); // ok
}

public static void DoMagicWrapper(this SomeClass someInstance)


{
someInstance.DoMagic(); // compilation error
}
}

Extension methods are just a syntactic sugar, and are not actually members of the class they extend. This means that
they cannot break encapsulation—they only have access to public (or when implemented in the same assembly,
internal) fields, properties and methods.

Section 48.6: Extension methods for chaining


When an extension method returns a value that has the same type as its this argument, it can be used to "chain" one or
more method calls with a compatible signature. This can be useful for sealed and/or primitive types, and allows the
creation of so-called "fluent" APIs if the method names read like natural human language.

void Main()
{
int result = 5.Increment().Decrement().Increment(); // result is now 6

public static class IntExtensions


{
public static int Increment(this int number) {
return ++number;
}

public static int Decrement(this int number) {


return --number;
}
}

INFOBYTE CAREER INSTITUTE 199


Or like this

void Main()
{
int[] ints = new[] { 1, 2, 3, 4, 5, 6};
int[] a = ints.WhereEven();
//a is { 2, 4, 6 };
int[] b = ints.WhereEven().WhereGreaterThan(2);
//b is { 4, 6 };
}

public static class IntArrayExtensions


{
public static int[] WhereEven(this int[] array)
{
//Enumerable.* extension methods use a fluent approach return
array.Where(i => (i%2) == 0).ToArray();
}

public static int[] WhereGreaterThan(this int[] array, int value)


{
return array.Where(i => i > value).ToArray();
}
}

Section 48.7: Extension methods with Enumeration


Extension methods are useful for adding functionality to enumerations.

One common use is to implement a conversion method.

public enum YesNo


{
Yes,
No,
}

public static class EnumExtentions


{
public static bool ToBool(this YesNo yn)
{
return yn == YesNo.Yes;
}
public static YesNo ToYesNo(this bool yn)
{
return yn ? YesNo.Yes : YesNo.No;
}
}

Now you can quickly convert your enum value to a different type. In this case a bool.

bool yesNoBool = YesNo.Yes.ToBool(); // yesNoBool == true


YesNo yesNoEnum = false.ToYesNo(); // yesNoEnum == YesNo.No

Alternatively extension methods can be used to add property like methods.

public enum Element


{
Hydrogen,

INFOBYTE CAREER INSTITUTE 200


Helium,
Lithium,
Beryllium,
Boron,
Carbon,
Nitrogen,
Oxygen
//Etc
}

public static class ElementExtensions


{
public static double AtomicMass(this Element element)
{
switch(element)
{
case Element.Hydrogen: return 1.00794;
case Element.Helium: return 4.002602;
case Element.Lithium: return 6.941;
case Element.Beryllium: return 9.012182;
case Element.Boron: return 10.811;
case Element.Carbon: return 12.0107;
case Element.Nitrogen: return 14.0067;
case Element.Oxygen: return 15.9994;
//Etc
}
return double.Nan;
}
}

var massWater = 2*Element.Hydrogen.AtomicMass() + Element.Oxygen.AtomicMass();

Section 48.8: Extension methods dispatch based on


static type
The static (compile-time) type is used rather than the dynamic (run-time type) to match parameters.

public class Base


{
public virtual string GetName()
{
return "Base";
}
}

public class Derived : Base


{
public override string GetName()
{
return "Derived";
}
}

public static class Extensions


{
public static string GetNameByExtension(this Base item)
{
return "Base";
}

public static string GetNameByExtension(this Derived item)

INFOBYTE CAREER INSTITUTE 201


{
return "Derived";
}
}

public static class Program


{
public static void Main()
{
Derived derived = new Derived();
Base @base = derived;

// Use the instance method "GetName"


Console.WriteLine(derived.GetName()); // Prints "Derived"
Console.WriteLine(@base.GetName()); // Prints "Derived"

// Use the static extension method "GetNameByExtension"


Console.WriteLine(derived.GetNameByExtension()); // Prints "Derived"
Console.WriteLine(@base.GetNameByExtension()); // Prints "Base"
}
}

Live Demo on .NET Fiddle

Also the dispatch based on static type does not allow an extension method to be called on a dynamic object:

public class Person


{
public string Name { get; set; }
}

public static class ExtenionPerson


{
public static string GetPersonName(this Person person)
{
return person.Name;
}
}

dynamic person = new Person { Name = "Jon" };


var name = person.GetPersonName(); // RuntimeBinderException is thrown

Section 48.9: Extension methods on Interfaces


One useful feature of extension methods is that you can create common methods for an interface. Normally an
interface cannot have shared implementations, but with extension methods they can.

public interface IVehicle


{
int MilesDriven { get; set; }
}

public static class Extensions


{
public static int FeetDriven(this IVehicle vehicle)
{
return vehicle.MilesDriven * 5028;
}
}

INFOBYTE CAREER INSTITUTE 202


In this example, the method FeetDriven can be used on any IVehicle. This logic in this method would apply to all IVehicles,
so it can be done this way so that there doesn't have to be a FeetDriven in the IVehicle definition which would be
implemented the same way for all children.

Section 48.10: Extension methods in combination


with interfaces
It is very convenient to use extension methods with interfaces as implementation can be stored outside of class and all it
takes to add some functionality to class is to decorate class with interface.

public interface IInterface


{
string Do()
}

public static class ExtensionMethods{


public static string DoWith(this IInterface obj){
//does something with IInterface instance
}
}

public class Classy : IInterface


{
this is a wrapper method; you could also call DoWith() on a Classy instance directly,
provided you import the namespace containing the extension method
public Do(){
return this.DoWith();
}
}

use like:

var classy = new Classy();


classy.Do(); // will call the extension
classy.DoWith(); // Classy implements IInterface so it can also be called this way

Section 48.11: Extension methods aren't supported


by dynamic code
static class Program
{
static void Main()
{
dynamic dynamicObject = new ExpandoObject();

string awesomeString = "Awesome";

// Prints True
Console.WriteLine(awesomeString.IsThisAwesome());

dynamicObject.StringValue = awesomeString;

// Prints True
Console.WriteLine(StringExtensions.IsThisAwesome(dynamicObject.StringValue));

No compile time error or warning, but on runtime throws RuntimeBinderException


Console.WriteLine(dynamicObject.StringValue.IsThisAwesome());
}

INFOBYTE CAREER INSTITUTE 203


}

static class StringExtensions


{
public static bool IsThisAwesome(this string value)
{
return value.Equals("Awesome");
}
}

The reason [calling extension methods from dynamic code] doesn't work is because in regular, non-dynamic
code extension methods work by doing a full search of all the classes known to the compiler for a static class
that has an extension method that matches. The search goes in order based on the namespace nesting and
available using directives in each namespace.

That means that in order to get a dynamic extension method invocation resolved correctly, somehow the DLR
has to know at runtime what all the namespace nestings and using directives were in your source code. We do
not have a mechanism handy for encoding all that information into the call site. We considered inventing such
a mechanism, but decided that it was too high cost and produced too much schedule risk to be worth it.

Source

Section 48.12: Extensions and interfaces together enable


DRY code and mixin-like functionality
Extension methods enable you to simplify your interface definitions by only including core required functionality in the
interface itself and allowing you to define convenience methods and overloads as extension methods. Interfaces with
fewer methods are easier to implement in new classes. Keeping overloads as extensions rather than including them in
the interface directly saves you from copying boilerplate code into every implementation, helping you keep your code
DRY. This in fact is similar to the mixin pattern which C# does not support.

System.Linq.Enumerable’s extensions to IEnumerable<T> is a great example of this. IEnumerable<T> only requires


the implementing class to implement two methods: generic and non-generic GetEnumerator(). But
System.Linq.Enumerable provides countless useful utilities as extensions enabling concise and clear consumption
of IEnumerable<T>.

The following is a very simple interface with convenience overloads provided as extensions.

public interface ITimeFormatter


{
string Format(TimeSpan span);
}

public static class TimeFormatter


{
Provide an overload to *all* implementers of ITimeFormatter. public static string
Format(
this ITimeFormatter formatter, int
millisecondsSpan)
=> formatter.Format(TimeSpan.FromMilliseconds(millisecondsSpan));
}

Implementations only need to provide one method. Very easy to


write additional implementations.

INFOBYTE CAREER INSTITUTE 204


public class SecondsTimeFormatter : ITimeFormatter
{
public string Format(TimeSpan span)
{
return $"{(int)span.TotalSeconds}s";
}
}

class Program
{
static void Main(string[] args)
{
var formatter = new SecondsTimeFormatter();
// Callers get two method overloads!
Console.WriteLine($"4500ms is rougly {formatter.Format(4500)}"); var span =
TimeSpan.FromSeconds(5);
Console.WriteLine($"{span} is formatted as {formatter.Format(span)}");
}
}

Section 48.13: IList<T> Extension Method Example:


Comparing 2 Lists
You can use the following extension method for comparing the contents of two IList< T > instances of the same type.

By default the items are compared based on their order within the list and the items themselves, passing false to the
isOrdered parameter will compare only the items themselves regardless of their order.

For this method to work, the generic type (T) must override both Equals and GetHashCode methods.

Usage:

List<string> list1 = new List<string> {"a1", "a2", null, "a3"};


List<string> list2 = new List<string> {"a1", "a2", "a3", null};

list1.Compare(list2);//this gives false


list1.Compare(list2, false);//this gives true. they are equal when the order is disregarded

Method:

public static bool Compare<T>(this IList<T> list1, IList<T> list2, bool isOrdered = true)
{
if (list1 == null && list2 == null)
return true;
if (list1 == null || list2 == null || list1.Count != list2.Count)
return false;

if (isOrdered)
{
for (int i = 0; i < list2.Count; i++)
{
var l1 = list1[i];
var l2 = list2[i];
if (
(l1 == null && l2 != null) ||
(l1 != null && l2 == null) ||
(!l1.Equals(l2)))
{

INFOBYTE CAREER INSTITUTE 205


return false;
}
}
return true;
}
else
{
List<T> list2Copy = new List<T>(list2);
//Can be done with Dictionary without O(n^2)
for (int i = 0; i < list1.Count; i++)
{
if (!list2Copy.Remove(list1[i]))
return false;
}
return true;
}
}

Section 48.14: Extension methods as strongly typed wrappers


Extension methods can be used for writing strongly typed wrappers for dictionary-like objects. For example a cache,
HttpContext.Items at cetera...

public static class CacheExtensions


{
public static void SetUserInfo(this Cache cache, UserInfo data) => cache["UserInfo"] =
data;

public static UserInfo GetUserInfo(this Cache cache) => cache["UserInfo"]


as UserInfo;
}

This approach removes the need of using string literals as keys all over the codebase as well as the need of casting to
the required type during the read operation. Overall it creates a more secure, strongly typed way of interacting with such
loosely typed objects as Dictionaries.

Section 48.15: Using Extension methods to create beautiful


mapper classes
We can create a better mapper classes with extension methods, Suppose if i have some DTO classes like

public class UserDTO


{
public AddressDTO Address { get; set; }
}

public class AddressDTO


{
public string Name { get; set; }
}

and i need to map to corresponding view model classes

public class UserViewModel


{
public AddressViewModel Address { get; set; }
}

INFOBYTE CAREER INSTITUTE 206


public class AddressViewModel
{
public string Name { get; set; }
}

then I can create my mapper class like below

public static class ViewModelMapper


{
public static UserViewModel ToViewModel(this UserDTO user)
{
return user == null ?
null :
new UserViewModel()
{
Address = user.Address.ToViewModel()
Job = user.Job.ToViewModel(),
Contact = user.Contact.ToViewModel() .. and so on
};
}

public static AddressViewModel ToViewModel(this AddressDTO userAddr)


{
return userAddr == null ?
null :
new AddressViewModel()
{
Name = userAddr.Name
};
}
}

Then finally i can invoke my mapper like below

UserDTO userDTOObj = new UserDTO() {


Address = new AddressDTO() {
Name = "Address of the user"
}
};

UserViewModel user = userDTOObj.ToViewModel(); // My DTO mapped to Viewmodel

The beauty here is all the mapping method have a common name (ToViewModel) and we can reuse it several ways

Section 48.16: Using Extension methods to build new


collection types (e.g. DictList)
You can create extension methods to improve usability for nested collections like a Dictionary with a List<T> value.

Consider the following extension methods:

public static class DictListExtensions


{
public static void Add<TKey, TValue, TCollection>(this Dictionary<TKey, TCollection> dict, TKey key, TValue value)

where TCollection : ICollection<TValue>, new()


{
TCollection list;

INFOBYTE CAREER INSTITUTE 207


if (!dict.TryGetValue(key, out list))
{
list = new TCollection();
dict.Add(key, list);
}

list.Add(value);
}

public static bool Remove<TKey, TValue, TCollection>(this Dictionary<TKey, TCollection> dict, TKey key, TValue value)

where TCollection : ICollection<TValue>


{
TCollection list;
if (!dict.TryGetValue(key, out list))
{
return false;
}

var ret = list.Remove(value);


if (list.Count == 0)
{
dict.Remove(key);
}
return ret;
}
}

you can use the extension methods as follows:

var dictList = new Dictionary<string, List<int>>();

dictList.Add("example", 5);
dictList.Add("example", 10);
dictList.Add("example", 15);

Console.WriteLine(String.Join(", ", dictList["example"])); // 5, 10, 15

dictList.Remove("example", 5);
dictList.Remove("example", 10);

Console.WriteLine(String.Join(", ", dictList["example"])); // 15

dictList.Remove("example", 15);

Console.WriteLine(dictList.ContainsKey("example")); // False

View Demo

Section 48.17: Extension methods for handling special cases


Extension methods can be used to "hide" processing of inelegant business rules that would otherwise require
cluttering up a calling function with if/then statements. This is similar to and analogous to handling nulls with
extension methods. For example,

public static class CakeExtensions


{
public static Cake EnsureTrueCake(this Cake cake)
{
//If the cake is a lie, substitute a cake from grandma, whose cakes aren't as tasty but are

INFOBYTE CAREER INSTITUTE 208


known never to be lies. If the cake isn't a lie, don't do anything and return it.
return CakeVerificationService.IsCakeLie(cake) ? GrandmasKitchen.Get1950sCake() : cake;
}
}

Cake myCake = Bakery.GetNextCake().EnsureTrueCake();


myMouth.Eat(myCake);//Eat the cake, confident that it is not a lie.

Section 48.18: Using Extension methods with Static


methods and Callbacks
Consider using Extension Methods as Functions which wrap other code, here's a great example that uses both a
static method and and extension method to wrap the Try Catch construct. Make your code Bullet Proof...

using System;
using System.Diagnostics;

namespace Samples
{
<summary>
Wraps a try catch statement as a static helper which uses
Extension methods for the exception
</summary>
public static class Bullet
{
<summary>
Wrapper for Try Catch Statement
</summary>
<param name="code">Call back for code</param>
<param name="error">Already handled and logged exception</param> public static
void Proof(Action code, Action<Exception> error)
{
try
{
code();
}
catch (Exception iox)
{
//extension method used here
iox.Log("BP2200-ERR-Unexpected Error"); //callback,
exception already handled and logged error(iox);

}
}
<summary>
Example of a logging method helper, this is the extension method
</summary>
<param name="error">The Exception to log</param>
<param name="messageID">A unique error ID header</param>
public static void Log(this Exception error, string messageID)
{
Trace.WriteLine(messageID);
Trace.WriteLine(error.Message);
Trace.WriteLine(error.StackTrace);
Trace.WriteLine("");
}
}
<summary>
Shows how to use both the wrapper and extension methods.
</summary>
public class UseBulletProofing

INFOBYTE CAREER INSTITUTE 209


{
public UseBulletProofing()
{
var ok = false;
var result = DoSomething();
if (!result.Contains("ERR"))
{
ok = true;
DoSomethingElse();
}
}

<summary>
How to use Bullet Proofing in your code.
</summary>
<returns>A string</returns>
public string DoSomething()
{
string result = string.Empty;
//Note that the Bullet.Proof method forces this construct.
Bullet.Proof(() =>
{
//this is the code callback
result = "DST5900-INF-No Exceptions in this code";
}, error =>
{
//error is the already logged and handled exception //determine the
base result
result = "DTS6200-ERR-An exception happened look at console log"; if
(error.Message.Contains("SomeMarker")) {

//filter the result for Something within the exception message result = "DST6500-
ERR-Some marker was found in the exception";
}
});
return result;
}

<summary>
Next step in workflow
</summary>
public void DoSomethingElse()
{
//Only called if no exception was thrown before
}
}
}

INFOBYTE CAREER INSTITUTE 210


Chapter 49: Named Arguments
Section 49.1: Argument order is not necessary
You can place named arguments in any order you want.

Sample Method:

public static string Sample(string left, string right)


{
return string.Join("-",left,right);
}

Call Sample:

Console.WriteLine (Sample(left:"A",right:"B"));
Console.WriteLine (Sample(right:"A",left:"B"));

Results:

A-B
B-A

Section 49.2: Named arguments and optional parameters


You can combine named arguments with optional parameters.

Let see this method:

public sealed class SmsUtil


{
public static bool SendMessage(string from, string to, string message, int retryCount = 5, object attachment = null)

{
// Some code
}
}

When you want to call this method without set retryCount argument :

var result = SmsUtil.SendMessage(


from : "Cihan",
to : "Yakar",
message : "Hello there!",
attachment : new object());

Section 49.3: Named Arguments can make your code more


clear
Consider this simple class:

class SmsUtil
{
public bool SendMessage(string from, string to, string message, int retryCount, object attachment)

INFOBYTE CAREER INSTITUTE 211


{
// Some code
}
}

Before C# 3.0 it was:

var result = SmsUtil.SendMessage("Mehran", "Maryam", "Hello there!", 12, null);

you can make this method call even more clear with named arguments:

var result = SmsUtil.SendMessage(


from: "Mehran",
to: "Maryam",
message "Hello there!",
retryCount: 12,
attachment: null);

INFOBYTE CAREER INSTITUTE 212


Chapter 50: Named and Optional
Arguments
Section 50.1: Optional Arguments
Consider preceding is our function definition with optional arguments.

private static double FindAreaWithOptional(int length, int width=56)


{
try
{
return (length * width);
}
catch (Exception)
{
throw new NotImplementedException();
}
}

Here we have set the value for width as optional and gave value as 56. If you note, the IntelliSense itself shows you the
optional argument as shown in the below image.

Console.WriteLine("Area with Optional Argument : ");


area = FindAreaWithOptional(120);
Console.WriteLine(area);
Console.Read();

Note that we did not get any error while compiling and it will give you an output as follows.

Using Optional Attribute.

Another way of implementing the optional argument is by using the [Optional] keyword. If you do not pass the

INFOBYTE CAREER INSTITUTE 213


value for the optional argument, the default value of that datatype is assigned to that argument. The Optional
keyword is present in “Runtime.InteropServices” namespace.

using System.Runtime.InteropServices;
private static double FindAreaWithOptional(int length, [Optional]int width)
{
try
{
return (length * width);
}
catch (Exception)
{
throw new NotImplementedException();
}
}

area = FindAreaWithOptional(120); //area=0

And when we call the function, we get 0 because the second argument is not passed and the default value of int is 0 and
so the product is 0.

Section 50.2: Named Arguments


Consider following is our function call.

FindArea(120, 56);

In this our first argument is length (ie 120) and second argument is width (ie 56). And we are calculating the area by that
function. And following is the function definition.

private static double FindArea(int length, int width)


{
try
{
return (length* width);
}
catch (Exception)
{
throw new NotImplementedException();
}
}

So in the first function call, we just passed the arguments by its position. Right?

double area;
Console.WriteLine("Area with positioned argument is: ");
area = FindArea(120, 56);
Console.WriteLine(area);
Console.Read();

If you run this, you will get an output as follows.

INFOBYTE CAREER INSTITUTE 214


Now here it comes the features of a named arguments. Please see the preceding function call.

Console.WriteLine("Area with Named argument is: ");


area = FindArea(length: 120, width: 56);
Console.WriteLine(area);
Console.Read();

Here we are giving the named arguments in the method call.

area = FindArea(length: 120, width: 56);

Now if you run this program, you will get the same result. We can give the names vice versa in the method call if we are
using the named arguments.

Console.WriteLine("Area with Named argument vice versa is: ");


area = FindArea(width: 120, length: 56);
Console.WriteLine(area);
Console.Read();

One of the important use of a named argument is, when you use this in your program it improves the readability of your
code. It simply says what your argument is meant to be, or what it is?.

You can give the positional arguments too. That means, a combination of both positional argument and named
argument.

Console.WriteLine("Area with Named argument Positional Argument : ");


area = FindArea(120, width: 56);
Console.WriteLine(area);
Console.Read();

In the above example we passed 120 as the length and 56 as a named argument for the parameter width.

There are some limitations too. We will discuss the limitation of a named arguments now.

Limitation of using a Named Argument

Named argument specification must appear after all fixed arguments have been specified.

INFOBYTE CAREER INSTITUTE 215


If you use a named argument before a fixed argument you will get a compile time error as follows.

Named argument specification must appear after all fixed arguments have been specified

INFOBYTE CAREER INSTITUTE 216


Chapter 51: Data Annotation
Section 51.1: Data Annotation Basics
Data annotations are a way of adding more contextual information to classes or members of a class. There are three
main categories of annotations:

Validation Attributes: add validation criteria to data


Display Attributes: specify how the data should be displayed to the user
Modelling Attributes: add information on usage and relationship with other classes

Usage

Here is an example where two ValidationAttribute and one DisplayAttribute are used:

class Kid
{
[Range(0, 18)] // The age cannot be over 18 and cannot be negative public int Age {
get; set; }
[StringLength(MaximumLength = 50, MinimumLength = 3)] // The name cannot be under 3 chars or more than 50 chars

public string Name { get; set; }


[DataType(DataType.Date)] // The birthday will be displayed as a date only (without the time) public DateTime Birthday {
get; set; }
}

Data annotations are mostly used in frameworks such as ASP.NET. For example, in ASP.NET MVC, when a model is
received by a controller method, ModelState.IsValid() can be used to tell if the received model respects all its
ValidationAttribute. DisplayAttribute is also used in ASP.NET MVC to determine how to display values on a web page.

Section 51.2: Creating a custom validation attribute


Custom validation attributes can be created by deriving from the ValidationAttribute base class, then overriding virtual
methods as needed.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class


NotABananaAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var inputValue = value as string;
var isValid = true;

if (!string.IsNullOrEmpty(inputValue))
{
isValid = inputValue.ToUpperInvariant() != "BANANA";
}

return isValid;
}
}

This attribute can then be used like this:

public class Model

INFOBYTE CAREER INSTITUTE 217


{
[NotABanana(ErrorMessage = "Bananas are not allowed.")] public string
FavoriteFruit { get; set; }
}

Section 51.3: Manually Execute Validation Attributes


Most of the times, validation attributes are use inside frameworks (such as ASP.NET). Those frameworks take care of
executing the validation attributes. But what if you want to execute validation attributes manually? Just use the Validator
class (no reflection needed).

Validation Context

Any validation needs a context to give some information about what is being validated. This can include various
information such as the object to be validated, some properties, the name to display in the error message, etc.

ValidationContext vc = new ValidationContext(objectToValidate); // The simplest form of validation context. It contains only a
reference to the object being validated.

Once the context is created, there are multiple ways of doing validation.

Validate an Object and All of its Properties


ICollection<ValidationResult> results = new List<ValidationResult>(); // Will contain the results of the validation

bool isValid = Validator.TryValidateObject(objectToValidate, vc, results, true); // Validates the object and its properties using the
previously created context.
The variable isValid will be true if everything is valid
The results variable contains the results of the validation

Validate a Property of an Object


ICollection<ValidationResult> results = new List<ValidationResult>(); // Will contain the results of the validation

bool isValid = Validator.TryValidatePropery(objectToValidate.PropertyToValidate, vc, results, true); // Validates the property


using the previously created context.
The variable isValid will be true if everything is valid
The results variable contains the results of the validation

And More

To learn more about manual validation see:

ValidationContext Class Documentation


Validator Class Documentation

Section 51.4: Validation Attributes


Validation attributes are used to enforce various validation rules in a declarative fashion on classes or class
members. All validation attributes derive from the ValidationAttribute base class.

Example: RequiredAttribute

When validated through the ValidationAttribute.Validate method, this attribute will return an error if the Name property is
null or contains only whitespace.

INFOBYTE CAREER INSTITUTE 218


public class ContactModel
{
[Required(ErrorMessage = "Please provide a name.")] public string
Name { get; set; }
}

Example: StringLengthAttribute

The StringLengthAttribute validates if a string is less than the maximum length of a string. It can optionally specify a
minimum length. Both values are inclusive.

public class ContactModel


{
[StringLength(20, MinimumLength = 5, ErrorMessage = "A name must be between five and twenty characters.")]

public string Name { get; set; }


}

Example: RangeAttribute

The RangeAttribute gives the maximum and minimum value for a numeric field.

public class Model


{
[Range(0.01, 100.00,ErrorMessage = "Price must be between 0.01 and 100.00")] public decimal Price
{ get; set; }
}

Example: CustomValidationAttribute

The CustomValidationAttribute class allows a custom static method to be invoked for validation. The custom method
must be static ValidationResult [MethodName] (object input).

public class Model


{
[CustomValidation(typeof(MyCustomValidation), "IsNotAnApple")] public string
FavoriteFruit { get; set; }
}

Method declaration:

public static class MyCustomValidation


{
public static ValidationResult IsNotAnApple(object input)
{
var result = ValidationResult.Success;

if (input?.ToString()?.ToUpperInvariant() == "APPLE")
{
result = new ValidationResult("Apples are not allowed.");
}

return result;
}
}

INFOBYTE CAREER INSTITUTE 219


Section 51.5: EditableAttribute (data modeling attribute)
EditableAttribute sets whether users should be able to change the value of the class property.

public class Employee


{
[Editable(false)]
public string FirstName { get; set; }
}

Simple usage example in XAML application

<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication="clr-namespace:WpfApplication"
Height="70" Width="360" Title="Display name example">

<Window.Resources>
<wpfApplication:EditableConverter x:Key="EditableConverter"/>
</Window.Resources>

<StackPanel Margin="5">
<!-- TextBox Text (FirstName property value) -->
<!-- TextBox IsEnabled (Editable attribute) -->
<TextBox Text="{Binding Employee.FirstName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Employee, Converter={StaticResource EditableConverter},
ConverterParameter=FirstName}"/>
</StackPanel>

</Window>

namespace WpfApplication
{
<summary>
Interaction logic for MainWindow.xaml
</summary>
public partial class MainWindow : Window
{
private Employee _employee = new Employee() { FirstName = "This is not editable"};

public MainWindow()
{
InitializeComponent();
DataContext = this;
}

public Employee Employee


{
get { return _employee; }
set { _employee = value; }
}
}
}

namespace WpfApplication
{
public class EditableConverter : IValueConverter

INFOBYTE CAREER INSTITUTE 220


{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return editable attribute's value for given instance property,
defaults to true if not found
var attribute = value.GetType()
.GetProperty(parameter.ToString())
.GetCustomAttributes(false)
.OfType<EditableAttribute>()
.FirstOrDefault();

return attribute != null ? attribute.AllowEdit : true;


}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo


culture)
{
throw new NotImplementedException();
}
}
}

INFOBYTE CAREER INSTITUTE 221


Chapter 52: Keywords
Keywords are predefined, reserved identifiers with special meaning to the compiler. They cannot be used as
identifiers in your program without the @ prefix. For example @if is a legal identifier but not the keyword if.

Section 52.1: as
The as keyword is an operator similar to a cast. If a cast is not possible, using as produces null rather than
resulting in an InvalidCastException.

expression as type is equivalent to expression is type ? (type)expression : (type)null with the caveat that as is only valid on
reference conversions, nullable conversions, and boxing conversions. User-defined conversions are not supported; a
regular cast must be used instead.

For the expansion above, the compiler generates code such that expression will only be evaluated once and use single
dynamic type check (unlike the two in the sample above).

as can be useful when expecting an argument to facilitate several types. Specifically it grants the user multiple options -
rather than checking every possibility with is before casting, or just casting and catching exceptions. It is best practice to
use 'as' when casting/checking an object which will cause only one unboxing penalty. Using is to check, then casting
will cause two unboxing penalties.

If an argument is expected to be an instance of a specific type, a regular cast is preferred as its purpose is more
clear to the reader.

Because a call to as may produce null, always check the result to avoid a NullReferenceException.

Example usage

object something = "Hello";


Console.WriteLine(something as string); //Hello
Console.Writeline(something as Nullable<int>); //null
Console.WriteLine(something as int?); //null

//This does NOT compile:


//destination type must be a reference type (or a nullable value type)
Console.WriteLine(something as int);

Live Demo on .NET Fiddle

Equivalent example without using as:

Console.WriteLine(something is string ? (string)something : (string)null);

This is useful when overriding the Equals function in custom classes.

class MyCustomClass
{

public override bool Equals(object obj)


{
MyCustomClass customObject = obj as MyCustomClass;

if it is null it may be really null


or it may be of a different type

INFOBYTE CAREER INSTITUTE 222


if (Object.ReferenceEquals(null, customObject))
{
If it is null then it is not equal to this instance. return false;

// Other equality controls specific to class


}

Section 52.2: goto


goto can be used to jump to a specific line inside the code, specified by a label.

goto as a:
Label:
void InfiniteHello()
{
sayHello:
Console.WriteLine("Hello!");
goto sayHello;
}

Live Demo on .NET Fiddle

Case statement:
enum Permissions { Read, Write };

switch (GetRequestedPermission())
{
case Permissions.Read:
GrantReadAccess();
break;

case Permissions.Write:
GrantWriteAccess();
goto case Permissions.Read; //People with write access also get read
}

Live Demo on .NET Fiddle

This is particularly useful in executing multiple behaviors in a switch statement, as C# does not support fall-through case
blocks.

Exception Retry
var exCount = 0;
retry:
try
{
//Do work
}
catch (IOException)
{
exCount++;
if (exCount < 3)
{
Thread.Sleep(100);

INFOBYTE CAREER INSTITUTE 223


goto retry;
}
throw;
}

Live Demo on .NET Fiddle

Similar to many languages, use of goto keyword is discouraged except the cases below.

Valid usages of goto which apply to C#:

Fall-through case in switch statement.

Multi-level break. LINQ can often be used instead, but it usually has worse performance.

Resource deallocation when working with unwrapped low-level objects. In C#, low-level objects should
usually be wrapped in separate classes.

Finite state machines, for example, parsers; used internally by compiler generated async/await state
machines.

Section 52.3: volatile


Adding the volatile keyword to a field indicates to the compiler that the field's value may be changed by multiple separate
threads. The primary purpose of the volatile keyword is to prevent compiler optimizations that assume only single-
threaded access. Using volatile ensures that the value of the field is the most recent value that is available, and the value
is not subject to the caching that non-volatile values are.

It is good practice to mark every variable that may be used by multiple threads as volatile to prevent unexpected
behavior due to behind-the-scenes optimizations. Consider the following code block:

public class Example


{
public int x;

public void DoStuff()


{
x = 5;

the compiler will optimize this to y = 15 var y = x + 10;

/* the value of x will always be the current value, but y will always be "15" */ Debug.WriteLine("x = " + x + ",
y = " + y);
}
}

In the above code-block, the compiler reads the statements x = 5 and y = x + 10 and determines that the value of y will
always end up as 15. Thus, it will optimize the last statement as y = 15. However, the variable x is in fact a public field and
the value of x may be modified at runtime through a different thread acting on this field separately. Now consider this
modified code-block. Do note that the field x is now declared as volatile.

public class Example


{
public volatile int x;

public void DoStuff()

INFOBYTE CAREER INSTITUTE 224


{
x = 5;

the compiler no longer optimizes this statement var y = x + 10;

/* the value of x and y will always be the correct values */ Debug.WriteLine("x =


" + x + ", y = " + y);
}
}

Now, the compiler looks for read usages of the field x and ensures that the current value of the field is always
retrieved. This ensures that even if multiple threads are reading and writing to this field, the current value of x is
always retrieved.

volatile can only be used on fields within classes or structs. The following is not valid:

public void MyMethod() { volatile int x; }

volatile can only be applied to fields of following types:

reference types or generic type parameters known to be reference types


primitive types such as sbyte, byte, short, ushort, int, uint, char, float, and bool enums
types based on byte, sbyte, short, ushort, int or uint
IntPtr and UIntPtr

Remarks:

The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock
statement to serialize access.
The volatile keyword can be applied to fields of reference types
The volatile keyword will not make operating on 64-bit primitives on a 32-bit platform atomic. Interlocked operations
such as Interlocked.Read and Interlocked.Exchange must still be used for safe multi-threaded access on these
platforms.

Section 52.4: checked, unchecked


The checked and unchecked keywords define how operations handle mathematical overflow. "Overflow" in the context of
the checked and unchecked keywords is when an integer arithmetic operation results in a value which is greater in
magnitude than the target data type can represent.

When overflow occurs within a checked block (or when the compiler is set to globally use checked arithmetic), an
exception is thrown to warn of undesired behavior. Meanwhile, in an unchecked block, overflow is silent: no exceptions
are thrown, and the value will simply wrap around to the opposite boundary. This can lead to subtle, hard to find bugs.

Since most arithmetic operations are done on values that are not large or small enough to overflow, most of the time,
there is no need to explicitly define a block as checked. Care needs to be taken when doing arithmetic on unbounded
input that may cause overflow, for example when doing arithmetic in recursive functions or while taking user input.

Neither checked nor unchecked affect floating point arithmetic operations.

When a block or expression is declared as unchecked, any arithmetic operations inside it are allowed to overflow without
causing an error. An example where this behavior is desired would be the calculation of a checksum, where

INFOBYTE CAREER INSTITUTE 225


the value is allowed to "wrap around" during calculation:

byte Checksum(byte[] data) {


byte result = 0;
for (int i = 0; i < data.Length; i++) {
result = unchecked(result + data[i]); // unchecked expression
}
return result;
}

One of the most common uses for unchecked is implementing a custom override for object.GetHashCode(), a type of
checksum. You can see the keyword's use in the answers to this question: What is the best algorithm for an overridden
System.Object.GetHashCode?.

When a block or expression is declared as checked, any arithmetic operation that causes an overflow results in an
OverflowException being thrown.

int SafeSum(int x, int y) {


checked { // checked block
return x + y;
}
}

Both checked and unchecked may be in block and expression form.

Checked and unchecked blocks do not affect called methods, only operators called directly in the current method. For
example, Enum.ToObject(), Convert.ToInt32(), and user-defined operators are not affected by custom checked/unchecked
contexts.

Note: The default overflow default behavior (checked vs. unchecked) may be changed in the Project Properties or
through the /checked[+|-] command line switch. It is common to default to checked operations for debug builds and
unchecked for release builds. The checked and unchecked keywords would then be used only where a default approach
does not apply and you need an explicit behavior to ensure correctness.

Section 52.5: virtual, override, new


virtual and override

The virtual keyword allows a method, property, indexer or event to be overridden by derived classes and present
polymorphic behavior. (Members are non-virtual by default in C#)

public class BaseClass


{
public virtual void Foo()
{
Console.WriteLine("Foo from BaseClass");
}
}

In order to override a member, the override keyword is used in the derived classes. (Note the signature of the
members must be identical)

public class DerivedClass: BaseClass


{
public override void Foo()
{

INFOBYTE CAREER INSTITUTE 226


Console.WriteLine("Foo from DerivedClass");
}
}

The polymorphic behavior of virtual members means that when invoked, the actual member being executed is
determined at runtime instead of at compile time. The overriding member in the most derived class the particular object
is an instance of will be the one executed.

In short, object can be declared of type BaseClass at compile time but if at runtime it is an instance of
DerivedClass then the overridden member will be executed:

BaseClass obj1 = new BaseClass();


obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();


obj1.Foo(); //Outputs "Foo from DerivedClass"

Overriding a method is optional:

public class SecondDerivedClass: DerivedClass {}

var obj1 = new SecondDerivedClass();


obj1.Foo(); //Outputs "Foo from DerivedClass"

new

Since only members defined as virtual are overridable and polymorphic, a derived class redefining a non virtual
member might lead to unexpected results.

public class BaseClass


{
public void Foo()
{
Console.WriteLine("Foo from BaseClass");
}
}

public class DerivedClass: BaseClass


{
public void Foo()
{
Console.WriteLine("Foo from DerivedClass");
}
}

BaseClass obj1 = new BaseClass();


obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();


obj1.Foo(); //Outputs "Foo from BaseClass" too!

When this happens, the member executed is always determined at compile time based on the type of the object.

If the object is declared of type BaseClass (even if at runtime is of a derived class) then the method of
BaseClass is executed
If the object is declared of type DerivedClass then the method of DerivedClass is executed.

This is usually an accident (When a member is added to the base type after an identical one was added to the

INFOBYTE CAREER INSTITUTE 227


derived type) and a compiler warning CS0108 is generated in those scenarios.

If it was intentional, then the new keyword is used to suppress the compiler warning (And inform other developers of
your intentions!). the behavior remains the same, the new keyword just suppresses the compiler warning.

public class BaseClass


{
public void Foo()
{
Console.WriteLine("Foo from BaseClass");
}
}

public class DerivedClass: BaseClass


{
public new void Foo()
{
Console.WriteLine("Foo from DerivedClass");
}
}

BaseClass obj1 = new BaseClass();


obj1.Foo(); //Outputs "Foo from BaseClass"

obj1 = new DerivedClass();


obj1.Foo(); //Outputs "Foo from BaseClass" too!

The usage of override is not optional

Unlike in C++, the usage of the override keyword is not optional:

public class A
{
public virtual void Foo()
{
}
}

public class B : A
{
public void Foo() // Generates CS0108
{
}
}

The above example also causes warning CS0108, because B.Foo() is not automatically overriding A.Foo(). Add override
when the intention is to override the base class and cause polymorphic behavior, add new when you want non-
polymorphic behavior and resolve the call using the static type. The latter should be used with caution, as it may cause
severe confusion.

The following code even results in an error:

public class A
{
public void Foo()
{
}
}

public class B : A

INFOBYTE CAREER INSTITUTE 228


{
public override void Foo() // Error: Nothing to override
{
}
}
Derived classes can introduce polymorphism

The following code is perfectly valid (although rare):

public class A
{
public void Foo()
{
Console.WriteLine("A");
}
}

public class B : A
{
public new virtual void Foo()
{
Console.WriteLine("B");
}
}

Now all objects with a static reference of B (and its derivatives) use polymorphism to resolve Foo(), while
references of A use A.Foo().

A a = new A();
a.Foo(); // Prints "A";
a = new B();
a.Foo(); // Prints "A";
B b = new B();
b.Foo(); // Prints "B";

Virtual methods cannot be private

The C# compiler is strict in preventing senseless constructs. Methods marked as virtual cannot be private.
Because a private method cannot be seen from a derived type, it couldn't be overwritten either. This fails to
compile:

public class A
{
private virtual void Foo() // Error: virtual methods cannot be private
{
}
}

Section 52.6: stackalloc


The stackalloc keyword creates a region of memory on the stack and returns a pointer to the start of that
memory. Stack allocated memory is automatically removed when the scope it was created in is exited.

//Allocate 1024 bytes. This returns a pointer to the first byte.


byte* ptr = stackalloc byte[1024];

//Assign some values...


ptr[0] = 109;
ptr[1] = 13;

INFOBYTE CAREER INSTITUTE 229


ptr[2] = 232;
...

Used in an unsafe context.

As with all pointers in C# there is no bounds checking on reads and assignments. Reading beyond the bounds of the
allocated memory will have unpredictable results - it may access some arbitrary location within memory or it may
cause an access violation exception.

//Allocate 1 byte
byte* ptr = stackalloc byte[1];

//Unpredictable results...
ptr[10] = 1;
ptr[-1] = 2;

Stack allocated memory is automatically removed when the scope it was created in is exited. This means that you
should never return the memory created with stackalloc or store it beyond the lifetime of the scope.

unsafe IntPtr Leak() {


//Allocate some memory on the stack
var ptr = stackalloc byte[1024];

//Return a pointer to that memory (this exits the scope of "Leak")


return new IntPtr(ptr);
}

unsafe void Bad() {


//ptr is now an invalid pointer, using it in any way will have //unpredictable results. This is
exactly the same as accessing beyond //the bounds of the pointer.

var ptr = Leak();


}

stackalloc can only be used when declaring and initialising variables. The following is not valid:

byte* ptr;
...
ptr = stackalloc byte[1024];

Remarks:

stackalloc should only be used for performance optimizations (either for computation or interop). This is due to the fact
that:

The garbage collector is not required as the memory is allocated on the stack rather than the heap - the
memory is released as soon as the variable goes out of scope
It is faster to allocate memory on the stack rather than the heap Increase
the chance of cache hits on the CPU due to the locality of data

Section 52.7: break


In a loop (for, foreach, do, while) the break statement aborts the execution of the innermost loop and returns to the code
after it. Also it can be used with yield in which it specifies that an iterator has come to an end.

for (var i = 0; i < 10; i++)


{

INFOBYTE CAREER INSTITUTE 230


if (i == 5)
{
break;
}
Console.WriteLine("This will appear only 5 times, as the break will stop the loop.");
}

Live Demo on .NET Fiddle

foreach (var stuff in stuffCollection)


{
if (stuff.SomeStringProp == null)
break;
If stuff.SomeStringProp for any "stuff" is null, the loop is aborted.
Console.WriteLine(stuff.SomeStringProp);
}

The break-statement is also used in switch-case constructs to break out of a case or default segment.

switch(a)
{
case 5:
Console.WriteLine("a was 5!");
break;

default:
Console.WriteLine("a was something else!");
break;
}

In switch statements, the 'break' keyword is required at the end of each case statement. This is contrary to some
languages that allow for 'falling through' to the next case statement in the series. Workarounds for this would include
'goto' statements or stacking the 'case' statements sequentially.

Following code will give numbers 0, 1, 2, ..., 9 and the last line will not be executed. yield break signifies the end of the
function (not just a loop).

public static IEnumerable<int> GetNumbers()


{
int i = 0;
while (true) {
if (i < 10) {
yield return i++;
} else {
yield break;
}
}
Console.WriteLine("This line will not be executed");
}

Live Demo on .NET Fiddle

Note that unlike some other languages, there is no way to label a particular break in C#. This means that in the case of
nested loops, only the innermost loop will be stopped:

foreach (var outerItem in outerList)


{
foreach (var innerItem in innerList)

INFOBYTE CAREER INSTITUTE 231


{
if (innerItem.ShoudBreakForWhateverReason)
This will only break out of the inner loop, the outer will continue: break;

}
}

If you want to break out of the outer loop here, you can use one of several different strategies, such as:

A goto statement to jump out of the whole looping structure.


A specific flag variable (shouldBreak in the following example) that can be checked at the end of each
iteration of the outer loop.
Refactoring the code to use a return statement in the innermost loop body, or avoid the whole nested loop
structure altogether.

bool shouldBreak = false;


while(comeCondition)
{
while(otherCondition)
{
if (conditionToBreak)
{
Either tranfer control flow to the label below...
goto endAllLooping;

OR use a flag, which can be checked in the outer loop: shouldBreak =


true;
}
}

if(shouldBreakNow)
{
break; // Break out of outer loop if flag was set to true
}
}

endAllLooping: // label from where control flow will continue

Section 52.8: const


const is used to represent values that will never change throughout the lifetime of the program. Its value is
constant from compile-time, as opposed to the readonly keyword, whose value is constant from run-time.

For example, since the speed of light will never change, we can store it in a constant.

const double c = 299792458; // Speed of light

double CalculateEnergy(double mass)


{
return mass * c * c;
}

This is essentially the same as having return mass * 299792458 * 299792458, as the compiler will directly substitute
c with its constant value.

As a result, c cannot be changed once declared. The following will produce a compile-time error:

const double c = 299792458; // Speed of light

INFOBYTE CAREER INSTITUTE 232


c = 500; //compile-time error

A constant can be prefixed with the same access modifiers as methods:

private const double c = 299792458;


public const double c = 299792458;
internal const double c = 299792458;

const members are static by nature. However using static explicitly is not permitted.

You can also define method-local constants:

double CalculateEnergy(double mass)


{
const c = 299792458;
return mass * c * c;
}

These can not be prefixed with a private or public keyword, since they are implicitly local to the method they are defined
in.

Not all types can be used in a const declaration. The value types that are allowed, are the pre-defined types sbyte, byte,
short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, and all enum types. Trying to declare const members with
other value types (such as TimeSpan or Guid) will fail at compile-time.

For the special pre-defined reference type string, constants can be declared with any value. For all other reference types,
constants can be declared but must always have the value null.

Because const values are known at compile-time, they are allowed as case labels in a switch statement, as
standard arguments for optional parameters, as arguments to attribute specifications, and so on.

If const values are used across different assemblies, care must be taken with versioning. For example, if assembly A
defines a public const int MaxRetries = 3;, and assembly B uses that constant, then if the value of MaxRetries is later changed
to 5 in assembly A (which is then re-compiled), that change will not be effective in assembly B unless assembly B is also
re-compiled (with a reference to the new version of A).

For that reason, if a value might change in future revisions of the program, and if the value needs to be publicly
visible, do not declare that value const unless you know that all dependent assemblies will be re-compiled whenever
something is changed. The alternative is using static readonly instead of const, which is resolved at runtime.

Section 52.9: async, await


The await keyword was added as part of C# 5.0 release which is supported from Visual Studio 2012 onwards. It
leverages Task Parallel Library (TPL) which made the multi-threading relatively easier. The async and await keywords
are used in pair in the same function as shown below. The await keyword is used to pause the current asynchronous
method's execution until the awaited asynchronous task is completed and/or its results returned. In order to use the await
keyword, the method that uses it must be marked with the async keyword.

Using async with void is strongly discouraged. For more info you can look here.

Example:

public async Task DoSomethingAsync()


{

INFOBYTE CAREER INSTITUTE 233


Console.WriteLine("Starting a useless process..."); Stopwatch
stopwatch = Stopwatch.StartNew();
int delay = await UselessProcessAsync(1000);
stopwatch.Stop();
Console.WriteLine("A useless process took {0} milliseconds to execute.",
stopwatch.ElapsedMilliseconds);
}

public async Task<int> UselessProcessAsync(int x)


{
await Task.Delay(x);
return x;
}

Output:

"Starting a useless process..."

**... 1 second delay... **

"A useless process took 1000 milliseconds to execute."

The keyword pairs async and await can be omitted if a Task or Task<T> returning method only returns a single
asynchronous operation.

Rather than this:

public async Task PrintAndDelayAsync(string message, int delay)


{
Debug.WriteLine(message);
await Task.Delay(x);
}

It is preferred to do this:

public Task PrintAndDelayAsync(string message, int delay)


{
Debug.WriteLine(message);
return Task.Delay(x);
}
Version = 5.0

In C# 5.0 await cannot be used in catch and finally.

Version ≥ 6.0

With C# 6.0 await can be used in catch and finally.

Section 52.10: for


Syntax: for (initializer; condition; iterator)

The for loop is commonly used when the number of iterations is known.
The statements in the initializer section run only once, before you enter the loop.
The condition section contains a boolean expression that's evaluated at the end of every loop iteration to

INFOBYTE CAREER INSTITUTE 234


determine whether the loop should exit or should run again.
The iterator section defines what happens after each iteration of the body of the loop.

This example shows how for can be used to iterate over the characters of a string:

string str = "Hello";


for (int i = 0; i < str.Length; i++)
{
Console.WriteLine(str[i]);
}

Output:

H
e
l
l
o

Live Demo on .NET Fiddle

All of the expressions that define a for statement are optional; for example, the following statement is used to create
an infinite loop:

for( ; ; )
{
// Your code here
}

The initializer section can contain multiple variables, so long as they are of the same type. The condition section can
consist of any expression which can be evaluated to a bool. And the iterator section can perform multiple actions
separated by comma:

string hello = "hello";


for (int i = 0, j = 1, k = 9; i < 3 && k > 0; i++, hello += i) { Console.WriteLine(hello);

Output:

hello
hello1
hello12

Live Demo on .NET Fiddle

Section 52.11: abstract


A class marked with the keyword abstract cannot be instantiated.

A class must be marked as abstract if it contains abstract members or if it inherits abstract members that it doesn't
implement. A class may be marked as abstract even if no abstract members are involved.

INFOBYTE CAREER INSTITUTE 235


Abstract classes are usually used as base classes when some part of the implementation needs to be specified by
another component.

abstract class Animal


{
string Name { get; set; }
public abstract void MakeSound();
}

public class Cat : Animal


{
public override void MakeSound()
{
Console.WriteLine("Meov meov");
}
}

public class Dog : Animal


{
public override void MakeSound()
{
Console.WriteLine("Bark bark");
}
}

Animal cat = new Cat(); Allowed due to Cat deriving from Animal
cat.MakeSound(); will print out "Meov meov"

Animal dog = new Dog(); Allowed due to Dog deriving from Animal
dog.MakeSound(); will print out "Bark bark"

Animal animal = new Animal(); // Not allowed due to being an abstract class

A method, property, or event marked with the keyword abstract indicates that the implementation for that member is
expected to be provided in a subclass. As mentioned above, abstract members can only appear in abstract
classes.

abstract class Animal


{
public abstract string Name { get; set; }
}

public class Cat : Animal


{
public override string Name { get; set; }
}

public class Dog : Animal


{
public override string Name { get; set; }
}

Section 52.12: fixed


The fixed statement fixes memory in one location. Objects in memory are usually moving arround, this makes
garbage collection possible. But when we use unsafe pointers to memory addresses, that memory must not be
moved.

We use the fixed statement to ensure that the garbage collector does not relocate the string data.

INFOBYTE CAREER INSTITUTE 236


Fixed Variables

var myStr = "Hello world!";

fixed (char* ptr = myStr)


{
myStr is now fixed (won't be [re]moved by the Garbage Collector).
We can now do something with ptr.
}

Used in an unsafe context.

Fixed Array Size

unsafe struct Example


{
public fixed byte SomeField[8];
public fixed char AnotherField[64];
}

fixed can only be used on fields in a struct (must also be used in an unsafe context).

Section 52.13: default


For classes, interfaces, delegate, array, nullable (such as int?) and pointer types, default(TheType) returns null:

class MyClass {}
Debug.Assert(default(MyClass) == null);
Debug.Assert(default(string) == null);

For structs and enums, default(TheType) returns the same as new TheType():

struct Coordinates
{
public int X { get; set; }
public int Y { get; set; }
}

struct MyStruct
{
public string Name { get; set; }
public Coordinates Location { get; set; }
public Coordinates? SecondLocation { get; set; }
public TimeSpan Duration { get; set; }
}

var defaultStruct = default(MyStruct);


Debug.Assert(defaultStruct.Equals(new MyStruct()));
Debug.Assert(defaultStruct.Location.Equals(new Coordinates()));
Debug.Assert(defaultStruct.Location.X == 0);
Debug.Assert(defaultStruct.Location.Y == 0);
Debug.Assert(defaultStruct.SecondLocation == null);
Debug.Assert(defaultStruct.Name == null);
Debug.Assert(defaultStruct.Duration == TimeSpan.Zero);

default(T) can be particularly useful when T is a generic parameter for which no constraint is present to decide whether
T is a reference type or a value type, for example:

INFOBYTE CAREER INSTITUTE 237


public T GetResourceOrDefault<T>(string resourceName)
{
if (ResourceExists(resourceName))
{
return (T)GetResource(resourceName);
}
else
{
return default(T);
}
}

Section 52.14: sealed


When applied to a class, the sealed modifier prevents other classes from inheriting from it.

class A { }
sealed class B : A { }
class C : B { } //error : Cannot derive from the sealed class

When applied to a virtual method (or virtual property), the sealed modifier prevents this method (property) from being
overridden in derived classes.

public class A
{
public sealed override string ToString() // Virtual method inherited from class Object
{
return "Do not override me!";
}
}

public class B: A
{
public override string ToString() // Compile time error
{
return "An attempt to override";
}
}

Section 52.15: is
Checks if an object is compatible with a given type, i.e. if an object is an instance of the BaseInterface type, or a type
that derives from BaseInterface:

interface BaseInterface {}
class BaseClass : BaseInterface {}
class DerivedClass : BaseClass {}

var d = new DerivedClass();


Console.WriteLine(d is DerivedClass); // True
Console.WriteLine(d is BaseClass); // True
Console.WriteLine(d is BaseInterface); // True
Console.WriteLine(d is object); // True
Console.WriteLine(d is string); // False

var b = new BaseClass();


Console.WriteLine(b is DerivedClass); // False
Console.WriteLine(b is BaseClass); // True

INFOBYTE CAREER INSTITUTE 238


Console.WriteLine(b is BaseInterface); // True
Console.WriteLine(b is object); // True
Console.WriteLine(b is string); // False

If the intent of the cast is to use the object, it is best practice to use the as keyword'

interface BaseInterface {}
class BaseClass : BaseInterface {}
class DerivedClass : BaseClass {}

var d = new DerivedClass();


Console.WriteLine(d is DerivedClass); // True - valid use of 'is'
Console.WriteLine(d is BaseClass); // True - valid use of 'is'

if(d is BaseClass){
var castedD = (BaseClass)d;
castedD.Method(); // valid, but not best practice
}

var asD = d as BaseClass;

if(asD!=null){
asD.Method(); //preferred method since you incur only one unboxing penalty
}

But, from C# 7 pattern matching feature extends the is operator to check for a type and declare a new variable at the
same time. Same code part with C# 7 :

Version ≥ 7.0

if(d is BaseClass asD ){


asD.Method();
}

Section 52.16: this


The this keyword refers to the current instance of class(object). That way two variables with the same name, one at the
class-level (a field) and one being a parameter (or local variable) of a method, can be distinguished.

public MyClass {
int a;

void set_a(int a)
{
//this.a refers to the variable defined outside of the method, //while a refers to the
passed parameter.
this.a = a;
}
}

Other usages of the keyword are chaining non-static constructor overloads:

public MyClass(int arg) : this(arg, null)


{
}

and writing indexers:

public string this[int idx1, string idx2]

INFOBYTE CAREER INSTITUTE 239


{
get { /* ... */ }
set { /* ... */ }
}

and declaring extension methods:

public static int Count<TItem>(this IEnumerable<TItem> source)


{
// ...
}

If there is no conflict with a local variable or parameter, it is a matter of style whether to use this or not, so
this.MemberOfType and MemberOfType would be equivalent in that case. Also see base keyword.

Note that if an extension method is to be called on the current instance, this is required. For example if your are inside
a non-static method of a class which implements IEnumerable<> and you want to call the extension Count from before,
you must use:

this.Count() // works like StaticClassForExtensionMethod.Count(this)

and this cannot be omitted there.

Section 52.17: readonly


The readonly keyword is a field modifier. When a field declaration includes a readonly modifier, assignments to that
field can only occur as part of the declaration or in a constructor in the same class.

The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field.
A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different
values depending on the constructor used.

The readonly keyword is often used when injecting dependencies.

class Person
{
readonly string _name;
readonly string _surname = "Surname";

Person(string name)
{
_name = name;
}
void ChangeName()
{
_name = "another name"; // Compile error
_surname = "another surname"; // Compile error
}
}

Note: Declaring a field readonly does not imply immutability. If the field is a reference type then the
content of the object can be changed. Readonly is typically used to prevent having the object being
overwritten and assigned only during instantiation of that object.

INFOBYTE CAREER INSTITUTE 240


Note: Inside the constructor a readonly field can be reassigned

public class Car


{
public double Speed {get; set;}
}

//In code

private readonly Car car = new Car();

private void SomeMethod()


{
car.Speed = 100;
}

Section 52.18: typeof


Returns the Type of an object, without the need to instantiate it.

Type type = typeof(string);


Console.WriteLine(type.FullName); //System.String
Console.WriteLine("Hello".GetType() == type); //True
Console.WriteLine("Hello".GetType() == typeof(string)); //True

Section 52.19: foreach


foreach is used to iterate over the elements of an array or the items within a collection which implements
IEnumerable✝ .

var lines = new string[] {


"Hello world!",
"How are you doing today?",
"Goodbye"
};

foreach (string line in lines)


{
Console.WriteLine(line);
}

This will output

"Hello world!"
"How are you doing today?"
"Goodbye"

Live Demo on .NET Fiddle

You can exit the foreach loop at any point by using the break keyword or move on to the next iteration using the
continue keyword.

var numbers = new int[] {1, 2, 3, 4, 5, 6};

foreach (var number in numbers)

INFOBYTE CAREER INSTITUTE 241


{
// Skip if 2
if (number == 2)
continue;

Stop iteration if 5 if
(number == 5)
break;

Console.Write(number + ", ");


}

// Prints: 1, 3, 4,

Live Demo on .NET Fiddle

Notice that the order of iteration is guaranteed only for certain collections such as arrays and List, but not
guaranteed for many other collections.

While IEnumerable is typically used to indicate enumerable collections, foreach only requires that the collection expose
publicly the object GetEnumerator() method, which should return an object that exposes the bool MoveNext() method and
the object Current { get; } property.

Section 52.20: dynamic


The dynamic keyword is used with dynamically typed objects. Objects declared as dynamic forego compile-time static
checks, and are instead evaluated at runtime.

using System;
using System.Dynamic;

dynamic info = new ExpandoObject();


info.Id = 123;
info.Another = 456;

Console.WriteLine(info.Another);
// 456

Console.WriteLine(info.DoesntExist);
// Throws RuntimeBinderException

The following example uses dynamic with Newtonsoft's library Json.NET, in order to easily read data from a
deserialized JSON file.

try
{
string json = @"{ x : 10, y : ""ho""}";
dynamic deserializedJson = JsonConvert.DeserializeObject(json);
int x = deserializedJson.x;
string y = deserializedJson.y;
// int z = deserializedJson.z; // throws RuntimeBinderException
}
catch (RuntimeBinderException e)
{
This exception is thrown when a property
that wasn't assigned to a dynamic variable is used
}

INFOBYTE CAREER INSTITUTE 242


There are some limitations associated with the dynamic keyword. One of them is the use of extension methods.
The following example adds an extension method for string: SayHello.

static class StringExtensions


{
public static string SayHello(this string s) => $"Hello {s}!";
}

The first approach will be to call it as usual (as for a string):

var person = "Person";


Console.WriteLine(person.SayHello());

dynamic manager = "Manager";


Console.WriteLine(manager.SayHello()); // RuntimeBinderException

No compilation error, but at runtime you get a RuntimeBinderException. The workaround for this will be to call the extension
method via the static class:

var helloManager = StringExtensions.SayHello(manager);


Console.WriteLine(helloManager);

Section 52.21: try, catch, finally, throw


try, catch, finally, and throw allow you to handle exceptions in your code.

var processor = new InputProcessor();

The code within the try block will be executed. If an exception occurs during execution of
this code, execution will pass to the catch block corresponding to the exception type. try

{
processor.Process(input);
}
If a FormatException is thrown during the try block, then this catch block
will be executed.
catch (FormatException ex)
{
Throw is a keyword that will manually throw an exception, triggering any catch block that is
waiting for that exception type.
throw new InvalidOperationException("Invalid input", ex);
}
catch can be used to catch all or any specific exceptions. This catch block,
with no type specified, catches any exception that hasn't already been caught
in a prior catch block.
catch
{
LogUnexpectedException();
throw; // Re-throws the original exception.
}
The finally block is executed after all try-catch blocks have been; either after the try has
succeeded in running all commands or after all exceptions have been caught.
finally
{
processor.Dispose();
}

Note: The return keyword can be used in try block, and the finally block will still be executed (just before

INFOBYTE CAREER INSTITUTE 243


returning). For example:

try
{
connection.Open();
return connection.Get(query);
}
finally
{
connection.Close();
}

The statement connection.Close() will execute before the result of connection.Get(query) is returned.

Section 52.22: void


The reserved word "void" is an alias of System.Void type, and has two uses:

1. Declare a method that doesn't have a return value:

public void DoSomething()


{
// Do some work, don't return any value to the caller.
}

A method with a return type of void can still have the return keyword in its body. This is useful when you want to exit the
method's execution and return the flow to the caller:

public void DoSomething()


{
// Do some work...

if (condition)
return;

// Do some more work if the condition evaluated to false.


}

2. Declare a pointer to an unknown type in an unsafe context.

In an unsafe context, a type may be a pointer type, a value type, or a reference type. A pointer type declaration is
usually type* identifier, where the type is a known type - i.e int* myInt, but can also be void* identifier, where the type is
unknown.

Note that declaring a void pointer type is discouraged by Microsoft.

Section 52.23: namespace


The namespace keyword is an organization construct that helps us understand how a codebase is arranged.
Namespaces in C# are virtual spaces rather than being in a physical folder.

namespace StackOverflow
{
namespace Documentation
{
namespace CSharp.Keywords
{

INFOBYTE CAREER INSTITUTE 244


public class Program
{
public static void Main()
{
Console.WriteLine(typeof(Program).Namespace);
//StackOverflow.Documentation.CSharp.Keywords
}
}
}
}
}

Namespaces in C# can also be written in chained syntax. The following is equivalent to above:

namespace StackOverflow.Documentation.CSharp.Keywords
{
public class Program
{
public static void Main()
{
Console.WriteLine(typeof(Program).Namespace);
//StackOverflow.Documentation.CSharp.Keywords
}
}
}

Section 52.24: ref, out


The ref and out keywords cause an argument to be passed by reference, not by value. For value types, this means that
the value of the variable can be changed by the callee.

int x = 5;
ChangeX(ref x);
// The value of x could be different now

For reference types, the instance in the variable can not only be modified (as is the case without ref), but it can also be
replaced altogether:

Address a = new Address();


ChangeFieldInAddress(a);
a will be the same instance as before, even if it is modified
CreateANewInstance(ref a);
a could be an entirely new instance now

The main difference between the out and ref keyword is that ref requires the variable to be initialized by the caller,
while out passes that responsibility to the callee.

To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.

int number = 1;
Console.WriteLine("Before AddByRef: " + number); // number = 1
AddOneByRef(ref number);
Console.WriteLine("After AddByRef: " + number); // number = 2 SetByOut(out
number);
Console.WriteLine("After SetByOut: " + number); // number = 34

void AddOneByRef(ref int value)


{

INFOBYTE CAREER INSTITUTE 245


value++;
}

void SetByOut(out int value)


{
value = 34;
}

Live Demo on .NET Fiddle

The following does not compile, because out parameters must have a value assigned before the method returns (it would
compile using ref instead):

void PrintByOut(out int value)


{
Console.WriteLine("Hello!");
}

using out keyword as Generic Modifier

out keyword can also be used in generic type parameters when defining generic interfaces and delegates. In this case,
the out keyword specifies that the type parameter is covariant.

Covariance enables you to use a more derived type than that specified by the generic parameter. This
allows for implicit conversion of classes that implement variant interfaces and implicit conversion of
delegate types. Covariance and contravariance are supported for reference types, but they are not
supported for value types. - MSDN

//if we have an interface like this


interface ICovariant<out R> { }

//and two variables like


ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();

then the following statement is valid


without the out keyword this would have thrown error iobj = istr; //
implicit conversion occurs here

Section 52.25: base


The base keyword is used to access members from a base class. It is commonly used to call base implementations of
virtual methods, or to specify which base constructor should be called.

Choosing a constructor

public class Child : SomeBaseClass {


public Child() : base("some string for the base class")
{
}
}

public class SomeBaseClass {


public SomeBaseClass()
{
// new Child() will not call this constructor, as it does not have a parameter

INFOBYTE CAREER INSTITUTE 246


}
public SomeBaseClass(string message)
{
new Child() will use this base constructor because of the specified parameter in Child's
constructor Console.WriteLine(message);

}
}

Calling base implementation of virtual method

public override void SomeVirtualMethod() {


Do something, then call base implementation
base.SomeVirtualMethod();
}

It is possible to use the base keyword to call a base implementation from any method. This ties the method call directly to
the base implementation, which means that even if new child classes override a virtual method, the base implementation
will still be called so this needs to be used with caution.

public class Parent


{
public virtual int VirtualMethod()
{
return 1;
}
}

public class Child : Parent


{
public override int VirtualMethod() {
return 11;
}

public int NormalMethod()


{
return base.VirtualMethod();
}

public void CallMethods()


{
Assert.AreEqual(11, VirtualMethod());

Assert.AreEqual(1, NormalMethod());
Assert.AreEqual(1, base.VirtualMethod());
}
}

public class GrandChild : Child


{
public override int VirtualMethod()
{
return 21;
}

public void CallAgain()


{
Assert.AreEqual(21, VirtualMethod());
Assert.AreEqual(11, base.VirtualMethod());

INFOBYTE CAREER INSTITUTE 247


Notice that the call to NormalMethod below still returns the value
from the extreme base class even though the method has been overridden
in the child class.
Assert.AreEqual(1, NormalMethod());
}
}

Section 52.26: float, double, decimal


float

float is an alias to the .NET datatype System.Single. It allows IEEE 754 single-precision floating point numbers to be
stored. This data type is present in mscorlib.dll which is implicitly referenced by every C# project when you create them.

Approximate range: -3.4 × 1038 to 3.4 × 1038

Decimal precision: 6-9 significant digits

Notation:

float f = 0.1259;
var f1 = 0.7895f; // f is literal suffix to represent float values

It should be noted that the float type often results in significant rounding errors. In applications where
precision is important, other data types should be considered.

double

double is an alias to the .NET datatype System.Double. It represents a double-precision 64-bit floating-point
number. This datatype is present in mscorlib.dll which is implicitly referenced in any C# project.

Range: ±5.0 × 10−324 to ±1.7 × 10308

Decimal precision: 15-16 significant digits

Notation:

double distance = 200.34; // a double value


double salary = 245; // an integer implicitly type-casted to double value var marks = 123.764D; //
D is literal suffix to represent double values

decimal

decimal is an alias to the .NET datatype System.Decimal. It represents a keyword indicates a 128-bit data type.
Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it
appropriate for financial and monetary calculations. This datatype is present in mscorlib.dll which is implicitly
referenced in any C# project.

Range: -7.9 × 1028 to 7.9 × 1028

Decimal precision: 28-29 significant digits

INFOBYTE CAREER INSTITUTE 248


Notation:

decimal payable = 152.25m; // a decimal value


var marks = 754.24m; // m is literal suffix to represent decimal values

Section 52.27: operator


Most of the built-in operators (including conversion operators) can be overloaded by using the operator keyword along
with the public and static modifiers.

The operators comes in three forms: unary operators, binary operators and conversion operators.

Unary and binary operators requires at least one parameter of same type as the containing type, and some
requires a complementary matching operator.

Conversion operators must convert to or from the enclosing type.

public struct Vector32


{

public Vector32(int x, int y)


{
X = x;
Y = y;
}

public int X { get; }


public int Y { get; }

public static bool operator ==(Vector32 left, Vector32 right)


=> left.X == right.X && left.Y == right.Y;

public static bool operator !=(Vector32 left, Vector32 right)


=> !(left == right);

public static Vector32 operator +(Vector32 left, Vector32 right)


=> new Vector32(left.X + right.X, left.Y + right.Y);

public static Vector32 operator +(Vector32 left, int right)


=> new Vector32(left.X + right, left.Y + right);

public static Vector32 operator +(int left, Vector32 right)


=> right + left;

public static Vector32 operator -(Vector32 left, Vector32 right)


=> new Vector32(left.X - right.X, left.Y - right.Y);

public static Vector32 operator -(Vector32 left, int right)


=> new Vector32(left.X - right, left.Y - right);

public static Vector32 operator -(int left, Vector32 right)


=> right - left;

public static implicit operator Vector64(Vector32 vector)


=> new Vector64(vector.X, vector.Y);

public override string ToString() => $"{{{X}, {Y}}}";

INFOBYTE CAREER INSTITUTE 249


public struct Vector64
{

public Vector64(long x, long y)


{
X = x;
Y = y;
}

public long X { get; }


public long Y { get; }

public override string ToString() => $"{{{X}, {Y}}}";

Example

var vector1 = new Vector32(15, 39);


var vector2 = new Vector32(87, 64);

Console.WriteLine(vector1 == vector2); // false


Console.WriteLine(vector1 != vector2); // true
Console.WriteLine(vector1 + vector2); // {102, 103}
Console.WriteLine(vector1 - vector2); // {-72, -25}

Section 52.28: char


A char is single letter stored inside a variable. It is built-in value type which takes two bytes of memory space. It
represents System.Char data type found in mscorlib.dll which is implicitly referenced by every C# project when you
create them.

There are multiple ways to do this.

char c = 'c';
char c = '\u0063'; //Unicode
char c = '\x0063'; //Hex
char c = (char)99;//Integral

A char can be implicitly converted to ushort, int, uint, long, ulong, float, double, or decimal and it will return the integer
value of that char.

ushort u = c;

returns 99 etc.

However, there are no implicit conversions from other types to char. Instead you must cast them.

ushort u = 99;
char c = (char)u;

Section 52.29: params


params allows a method parameter to receive a variable number of arguments, i.e. zero, one or multiple arguments are
allowed for that parameter.

INFOBYTE CAREER INSTITUTE 250


static int AddAll(params int[] numbers)
{
int total = 0;
foreach (int number in numbers)
{
total += number;
}

return total;
}

This method can now be called with a typical list of int arguments, or an array of ints.

AddAll(5, 10, 15, 20); // 50


AddAll(new int[] { 5, 10, 15, 20 }); // 50

params must appear at most once and if used, it must be last in the argument list, even if the succeeding type is
different to that of the array.

Be careful when overloading functions when using the params keyword. C# prefers matching more specific
overloads before resorting to trying to use overloads with params. For example if you have two methods:

static double Add(params double[] numbers)


{
Console.WriteLine("Add with array of doubles");
double total = 0.0;
foreach (double number in numbers)
{
total += number;
}

return total;
}

static int Add(int a, int b)


{
Console.WriteLine("Add with 2 ints");
return a + b;
}

Then the specific 2 argument overload will take precedence before trying the params overload.

Add(2, 3); //prints "Add with 2 ints"


Add(2, 3.0); //prints "Add with array of doubles" (doubles are not ints)
Add(2, 3, 4); //prints "Add with array of doubles" (no 3 argument overload)

Section 52.30: while


The while operator iterates over a block of code until the conditional query equals false or the code is interrupted with a
goto, return, break or throw statement.

Syntax for while keyword:

while( condition ) { code block; }

Example:

INFOBYTE CAREER INSTITUTE 251


int i = 0;
while (i++ < 5)
{
Console.WriteLine("While is on loop number {0}.", i);
}

Output:

"While is on loop number 1."


"While is on loop number 2."
"While is on loop number 3."
"While is on loop number 4."
"While is on loop number 5."

Live Demo on .NET Fiddle

A while loop is Entry Controlled, as the condition is checked before the execution of the enclosed code block. This
means that the while loop wouldn't execute its statements if the condition is false.

bool a = false;

while (a == true)
{
Console.WriteLine("This will never be printed.");
}

Giving a while condition without provisioning it to become false at some point will result in an infinite or endless loop. As
far as possible, this should be avoided, however, there may be some exceptional circumstances when you need this.

You can create such a loop as follows:

while (true)
{
//...
}

Note that the C# compiler will transform loops such as

while (true)
{
...
}

or

for(;;)
{
...
}

into

{
:label

INFOBYTE CAREER INSTITUTE 252


// ...
goto label;
}

Note that a while loop may have any condition, no matter how complex, as long as it evaluates to (or returns) a boolean
value (bool). It may also contain a function that returns a boolean value (as such a function evaluates to the same type as
an expression such as `a==x'). For example,

while (AgriculturalService.MoreCornToPick(myFarm.GetAddress()))
{
myFarm.PickCorn();
}

Section 52.31: null


A variable of a reference type can hold either a valid reference to an instance or a null reference. The null reference is
the default value of reference type variables, as well as nullable value types.

null is the keyword that represents a null reference.

As an expression, it can be used to assign the null reference to variables of the aforementioned types:

object a = null;
string b = null;
int? c = null;
List<int> d = null;

Non-nullable value types cannot be assigned a null reference. All the following assignments are invalid:

int a = null;
float b = null;
decimal c = null;

The null reference should not be confused with valid instances of various types such as:

an empty list (new List<int>())


an empty string ("")
the number zero (0, 0f, 0m)
the null character ( '\0' )

Sometimes, it is meaningful to check if something is either null or an empty/default object. The


System.String.IsNullOrEmpty(String) method may be used to check this, or you may implement your own equivalent
method.

private void GreetUser(string userName)


{
if (String.IsNullOrEmpty(userName))
{
//The method that called us either sent in an empty string, or they sent us a null reference.
Either way, we need to report the problem.
throw new InvalidOperationException("userName may not be null or empty.");
}
else
{
//userName is acceptable.
Console.WriteLine("Hello, " + userName + "!");
}

INFOBYTE CAREER INSTITUTE 253


}

Section 52.32: continue


Immediately pass control to the next iteration of the enclosing loop construct (for, foreach, do, while):

for (var i = 0; i < 10; i++)


{
if (i < 5)
{
continue;
}
Console.WriteLine(i);
}

Output:

5
6
7
8
9

Live Demo on .NET Fiddle

var stuff = new [] {"a", "b", null, "c", "d"};

foreach (var s in stuff)


{
if (s == null)
{
continue;
}
Console.WriteLine(s);
}

Output:

a
b
c
d

Live Demo on .NET Fiddle

Section 52.33: string


string is an alias to the .NET datatype System.String, which allows text (sequences of characters) to be stored.

Notation:

string a = "Hello";
var b = "world";

INFOBYTE CAREER INSTITUTE 254


var f = new string(new []{ 'h', 'i', '!' }); // hi!

Each character in the string is encoded in UTF-16, which means that each character will require a minimum 2 bytes of
storage space.

Section 52.34: return

MSDN: The return statement terminates execution of the method in which it appears and returns control to the
calling method. It can also return an optional value. If the method is a void type, the return statement can be
omitted.

public int Sum(int valueA, int valueB)


{
return valueA + valueB;
}

public void Terminate(bool terminateEarly)


{
if (terminateEarly) return; // method returns to caller if true was passed in else Console.WriteLine("Not
early"); // prints only if terminateEarly was false
}

Section 52.35: unsafe


The unsafe keyword can be used in type or method declarations or to declare an inline block.

The purpose of this keyword is to enable the use of the unsafe subset of C# for the block in question. The unsafe
subset includes features like pointers, stack allocation, C-like arrays, and so on.

Unsafe code is not verifiable and that's why its usage is discouraged. Compilation of unsafe code requires passing a
switch to the C# compiler. Additionally, the CLR requires that the running assembly has full trust.

Despite these limitations, unsafe code has valid usages in making some operations more performant (e.g. array
indexing) or easier (e.g. interop with some unmanaged libraries).

As a very simple example

compile with /unsafe class


UnsafeTest
{
unsafe static void SquarePtrParam(int* p)
{
*p *= *p; // the '*' dereferences the pointer.
//Since we passed in "the address of i", this becomes "i *= i"
}

unsafe static void Main()


{
int i = 5;
// Unsafe method: uses address-of operator (&):
SquarePtrParam(&i); // "&i" means "the address of i". The behavior is similar to "ref i" Console.WriteLine(i); // Output:
25
}
}

INFOBYTE CAREER INSTITUTE 255


While working with pointers, we can change the values of memory locations directly, rather than having to address them
by name. Note that this often requires the use of the fixed keyword to prevent possible memory corruption as the garbage
collector moves things around (otherwise, you may get error CS0212). Since a variable that has been "fixed" cannot be
written to, we also often have to have a second pointer that starts out pointing to the same location as the first.

void Main()
{
int[] intArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

UnsafeSquareArray(intArray);
foreach(int i in intArray)
Console.WriteLine(i);
}

unsafe static void UnsafeSquareArray(int[] pArr)


{
int len = pArr.Length;

//in C or C++, we could say


int* a = &(pArr[0])
however, C# requires you to "fix" the variable first fixed(int*
fixedPointer = &(pArr[0]))
{
//Declare a new int pointer because "fixedPointer" cannot be written to.
"p" points to the same address space, but we can modify it
int* p = fixedPointer;

for (int i = 0; i < len; i++)


{
*p *= *p; //square the value, just like we did in SquarePtrParam, above
p++; //move the pointer to the next memory space.
NOTE that the pointer will move 4 bytes since "p" is an
int pointer and an int takes 4 bytes

//the above 2 lines could be written as one, like this:


// "*p *= *p++;"
}
}
}

Output:

1
4
9
16
25
36
49
64
81
100

unsafe also allows the use of stackalloc which will allocate memory on the stack like _alloca in the C run-time
library. We can modify the above example to use stackalloc as follows:

unsafe void Main()


{

INFOBYTE CAREER INSTITUTE 256


const int len=10;
int* seedArray = stackalloc int[len];

//We can no longer use the initializer "{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}" as before.


We have at least 2 options to populate the array. The end result of either
option will be the same (doing both will also be the same here).

//FIRST OPTION:
int* p = seedArray; // we don't want to lose where the array starts, so we
create a shadow copy of the pointer for(int
i=1; i<=len; i++)
*p++ = i;
//end of first option

//SECOND OPTION:
for(int i=0; i<len; i++)
seedArray[i] = i+1;
//end of second option

UnsafeSquareArray(seedArray, len);
for(int i=0; i< len; i++)
Console.WriteLine(seedArray[i]);
}

//Now that we are dealing directly in pointers, we don't need to mess around with
"fixed", which dramatically simplifies the code unsafe static void
UnsafeSquareArray(int* p, int len)
{
for (int i = 0; i < len; i++) *p *= *p++;

(Output is the same as above)

Section 52.36: switch


The switch statement is a control statement that selects a switch section to execute from a list of candidates. A switch
statement includes one or more switch sections. Each switch section contains one or more case labels followed by one
or more statements. If no case label contains a matching value, control is transferred to the default section, if there is
one. Case fall-through is not supported in C#, strictly speaking. However, if 1 or more case labels are empty, execution
will follow the code of the next case block which contains code. This allows grouping of multiple case labels with the
same implementation. In the following example, if month equals 12, the code in case 2 will be executed since the case
labels 12 1 and 2 are grouped. If a case block is not empty, a break must be present before the next case label,
otherwise the compiler will flag an error.

int month = DateTime.Now.Month; // this is expected to be 1-12 for Jan-Dec

switch (month)
{
case 12:
case 1:
case 2:
Console.WriteLine("Winter");
break;
case 3:
case 4:
case 5:
Console.WriteLine("Spring");
break;

INFOBYTE CAREER INSTITUTE 257


case 6:
case 7:
case 8:
Console.WriteLine("Summer");
break;
case 9:
case 10:
case 11:
Console.WriteLine("Autumn");
break;
default:
Console.WriteLine("Incorrect month index");
break;
}

A case can only be labeled by a value known at compile time (e.g. 1, "str", Enum.A), so a variable isn't a valid case label,
but a const or an Enum value is (as well as any literal value).

Section 52.37: var


An implicitly-typed local variable that is strongly typed just as if the user had declared the type. Unlike other variable
declarations, the compiler determines the type of variable that this represents based on the value that is assigned to it.

var i = 10; // implicitly typed, the compiler must determine what type of variable this is int i = 10; // explicitly typed, the
type of variable is explicitly stated to the compiler

// Note that these both represent the same type of variable (int) with the same value (10).

Unlike other types of variables, variable definitions with this keyword need to be initialized when declared. This is due
to the var keyword representing an implicitly-typed variable.

var i;
i = 10;

// This code will not run as it is not initialized upon declaration.

The var keyword can also be used to create new datatypes on the fly. These new datatypes are known as anonymous
types. They are quite useful, as they allow a user to define a set of properties without having to explicitly declare any kind
of object type first.

Plain anonymous type

var a = new { number = 1, text = "hi" };

LINQ query that returns an anonymous type

public class Dog


{
public string Name { get; set; }
public int Age { get; set; }
}

public class DogWithBreed


{
public Dog Dog { get; set; }
public string BreedName { get; set; }

INFOBYTE CAREER INSTITUTE 258


}

public void GetDogsWithBreedNames()


{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
DogName = d.Name,
BreedName = b.BreedName
};

DoStuff(result);
}

You can use var keyword in foreach statement

public bool hasItemInList(List<String> list, string stringToSearch)


{
foreach(var item in list)
{
if( ( (string)item ).equals(stringToSearch) )
return true;
}

return false;
}

Section 52.38: when


The when is a keyword added in C# 6, and it is used for exception filtering.

Before the introduction of the when keyword, you could have had one catch clause for each type of exception; with the
addition of the keyword, a more fine-grained control is now possible.

A when expression is attached to a catch branch, and only if the when condition is true, the catch clause will be
executed. It is possible to have several catch clauses with the same exception class types, and different when
conditions.

private void CatchException(Action action)


{
try
{
action.Invoke();
}

// exception filter
catch (Exception ex) when (ex.Message.Contains("when"))
{
Console.WriteLine("Caught an exception with when");
}

catch (Exception ex)


{
Console.WriteLine("Caught an exception without when");
}
}

INFOBYTE CAREER INSTITUTE 259


private void Method1() { throw new Exception("message for exception with when"); } private void Method2() {
throw new Exception("message for general exception"); }

CatchException(Method1);
CatchException(Method2);

Section 52.39: lock


lock provides thread-safety for a block of code, so that it can be accessed by only one thread within the same
process. Example:

private static object _lockObj = new object();


static void Main(string[] args)
{
Task.Run(() => TaskWork());
Task.Run(() => TaskWork());
Task.Run(() => TaskWork());

Console.ReadKey();
}

private static void TaskWork()


{
lock(_lockObj)
{
Console.WriteLine("Entered");

Task.Delay(3000);
Console.WriteLine("Done Delaying");

// Access shared resources safely

Console.WriteLine("Leaving");
}
}

Output:

Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving

Use cases:

Whenever you have a block of code that might produce side-effects if executed by multiple threads at the same time.
The lock keyword along with a shared synchronization object (_objLock in the example) can be used to prevent
that.

Note that _objLock can't be null and multiple threads executing the code must use the same object instance (either
by making it a static field, or by using the same class instance for both threads)

From the compiler side, the lock keyword is a syntactic sugar that is replaced by Monitor.Enter(_lockObj); and

INFOBYTE CAREER INSTITUTE 260


Monitor.Exit(_lockObj);. So if you replace the lock by surrounding the block of code with these two methods, you would
get the same results. You can see actual code in Syntactic sugar in C# - lock example

Section 52.40: uint


An unsigned integer, or uint, is a numeric datatype that only can hold positive integers. Like it's name suggests, it
represents an unsigned 32-bit integer. The uint keyword itself is an alias for the Common Type System type
System.UInt32. This datatype is present in mscorlib.dll, which is implicitly referenced by every C# project when you create
them. It occupies four bytes of memory space.

Unsigned integers can hold any value from 0 to 4,294,967,295.

Examples on how and now not to declare unsigned integers

uint i = 425697; // Valid expression, explicitly stated to compiler


var i1 = 789247U; // Valid expression, suffix allows compiler to determine datatype uint x = 3.0; // Error, there is
no implicit conversion

Please note: According to Microsoft, it is recommended to use the int datatype wherever possible as the uint
datatype is not CLS-compliant.

Section 52.41: if, if...else, if... else if


The if statement is used to control the flow of the program. An if statement identifies which statement to run based on
the value of a Boolean expression.

For a single statement, the braces{} are optional but recommended.

int a = 4;
if(a % 2 == 0)
{
Console.WriteLine("a contains an even number");
}
// output: "a contains an even number"

The if can also have an else clause, that will be executed in case the condition evaluates to false:

int a = 5;
if(a % 2 == 0)
{
Console.WriteLine("a contains an even number");
}
else
{
Console.WriteLine("a contains an odd number");
}
// output: "a contains an odd number"

The if...else if construct lets you specify multiple conditions:

int a = 9;
if(a % 2 == 0)
{
Console.WriteLine("a contains an even number");
}
else if(a % 3 == 0)

INFOBYTE CAREER INSTITUTE 261


{
Console.WriteLine("a contains an odd number that is a multiple of 3");
}
else
{
Console.WriteLine("a contains an odd number");
}
// output: "a contains an odd number that is a multiple of 3"

Important to note that if a condition is met in the above example , the control skips other tests and jumps to the
end of that particular if else construct.So, the order of tests is important if you are using if .. else if construct

C# Boolean expressions use short-circuit evaluation. This is important in cases where evaluating conditions may have
side effects:

if (someBooleanMethodWithSideEffects() && someOtherBooleanMethodWithSideEffects()) {


//...
}

There's no guarantee that someOtherBooleanMethodWithSideEffects will actually run.

It's also important in cases where earlier conditions ensure that it's "safe" to evaluate later ones. For example:

if (someCollection != null && someCollection.Count > 0) { // ..

The order is very important in this case because, if we reverse the order:

if (someCollection.Count > 0 && someCollection != null) {

it will throw a NullReferenceException if someCollection is null.

Section 52.42: static


The static modifier is used to declare a static member, which does not need to be instantiated in order to be
accessed, but instead is accessed simply through its name, i.e. DateTime.Now.

static can be used with classes, fields, methods, properties, operators, events, and constructors.

While an instance of a class contains a separate copy of all instance fields of the class, there is only one copy of
each static field.

class A
{
static public int count = 0;

public A()
{
count++;
}
}

class Program
{
static void Main(string[] args)

INFOBYTE CAREER INSTITUTE 262


{
A a = new A();
A b = new A();
A c = new A();

Console.WriteLine(A.count); // 3
}
}

count equals to the total number of instances of A class.

The static modifier can also be used to declare a static constructor for a class, to initialize static data or run code that
only needs to be called once. Static constructors are called before the class is referenced for the first time.

class A
{
static public DateTime InitializationTime;

Static constructor static


A()
{
InitializationTime = DateTime.Now;
Guaranteed to only run once
Console.WriteLine(InitializationTime.ToString());
}
}

A static class is marked with the static keyword, and can be used as a beneficial container for a set of methods that work
on parameters, but don't necessarily require being tied to an instance. Because of the static nature of the class, it cannot
be instantiated, but it can contain a static constructor. Some features of a static class include:

Can't be inherited
Can't inherit from anything other than Object
Can contain a static constructor but not an instance constructor
Can only contain static members
Is sealed

The compiler is also friendly and will let the developer know if any instance members exist within the class. An
example would be a static class that converts between US and Canadian metrics:

static class ConversionHelper {


private static double oneGallonPerLitreRate = 0.264172;

public static double litreToGallonConversion(int litres) { return litres *


oneGallonPerLitreRate;
}
}

When classes are declared static:

public static class Functions


{
public static int Double(int value)
{
return value + value;
}

INFOBYTE CAREER INSTITUTE 263


}

all function, properties or members within the class also need to be declared static. No instance of the class can be
created. In essence a static class allows you to create bundles of functions that are grouped together logically.

Since C#6 static can also be used alongside using to import static members and methods. They can be used then without
class name.

Old way, without using static:

using System;

public class ConsoleApplication


{
public static void Main()
{
Console.WriteLine("Hello World!"); //Writeline is method belonging to static class Console
}

Example with using static

using static System.Console;

public class ConsoleApplication


{
public static void Main()
{
WriteLine("Hello World!"); //Writeline is method belonging to static class Console
}

Drawbacks

While static classes can be incredibly useful, they do come with their own caveats:

Once the static class has been called, the class is loaded into memory and cannot be run through the
garbage collector until the AppDomain housing the static class is unloaded.

A static class cannot implement an interface.

Section 52.43: internal


The internal keyword is an access modifier for types and type members. Internal types or members are
accessible only within files in the same assembly

usage:

public class BaseClass


{
Only accessible within the same assembly internal
static int x = 0;
}

The difference between different access modifiers is clarified here

INFOBYTE CAREER INSTITUTE 264


Access modifiers

public

The type or member can be accessed by any other code in the same assembly or another assembly that
references it.

private

The type or member can only be accessed by code in the same class or struct.

protected

The type or member can only be accessed by code in the same class or struct, or in a derived class.

internal

The type or member can be accessed by any code in the same assembly, but not from another assembly.

protected internal

The type or member can be accessed by any code in the same assembly, or by any derived class in
another assembly.

When no access modifier is set, a default access modifier is used. So there is always some form of access modifier
even if it's not set.

Section 52.44: using


There are two types of using keyword usage, using statement and using directive:

using statement:

The using keyword ensures that objects that implement the IDisposable interface are properly disposed after
usage. There is a separate topic for the using statement

using directive

The using directive has three usages, see the msdn page for the using directive. There is a separate topic for the
using directive.

Section 52.45: where


where can serve two purposes in C#: type constraining in a generic argument, and filtering LINQ queries.

INFOBYTE CAREER INSTITUTE 265


In a generic class, let's consider

public class Cup<T>


{
// ...
}

T is called a type parameter. The class definition can impose constraints on the actual types that can be supplied for T.

The following kinds of constraints can be applied:

value type
reference type
default constructor
inheritance and implementation

value type

In this case only structs (this includes 'primitive' data types such as int, boolean etc) can be supplied

public class Cup<T> where T : struct


{
// ...
}

reference type

In this case only class types can be supplied

public class Cup<T> where T : class


{
// ...
}

hybrid value/reference type

Occasionally it is desired to restrict type arguments to those available in a database, and these will usually map to
value types and strings. As all type restrictions must be met, it is not possible to specify where T : struct or string (this is
not valid syntax). A workaround is to restrict type arguments to IConvertible which has built in