Csharp Language PDF
Csharp Language PDF
#c#
Table of Contents
About 1
Remarks 2
Versions 2
Examples 2
Explanation 3
Creating a new project in Visual Studio (console application) and Running it in Debug mode 5
Examples 22
Syntax tree 22
Semantic model 22
Remarks 24
Examples 24
public 24
private 24
internal 25
protected 25
protected internal 26
Introduction 30
Examples 30
Examples 33
ADO.NET Connections 33
Connection Strings 35
Examples 37
Examples 39
Examples 41
HashSet 41
SortedSet 41
T[ ] (Array of T) 41
List 42
Dictionary 42
Stack 43
LinkedList 43
Queue 44
Examples 45
Creating an anonymous type 45
Anonymous vs dynamic 45
Syntax 48
Remarks 48
Examples 48
Array covariance 49
Declaring an array 49
Multi-dimensional arrays 51
Jagged arrays 51
Copying arrays 54
Usage: 55
Introduction 57
Examples 57
How to implement password reset token in asp.net identity using user manager. 57
Remarks 61
Examples 61
[AssemblyTitle] 61
[AssemblyProduct] 61
Global and local AssemblyInfo 61
[AssemblyVersion] 62
Automated versioning 62
Common fields 63
[AssemblyConfiguration] 63
[InternalsVisibleTo] 63
[AssemblyKeyFile] 64
Remarks 65
Examples 65
Blocking 65
ConfigureAwait 66
Async/await 67
BackgroundWorker 68
Task 69
Thread 70
Introduction 72
Remarks 72
Examples 72
Try/Catch/Finally 72
Concurrent calls 74
Async/await will only improve performance if it allows the machine to do additional work 78
Remarks 80
Examples 81
Examples 89
Using an attribute 89
Reading an attribute 89
DebuggerDisplay Attribute 90
Obsolete Attribute 93
Syntax 94
Remarks 94
Examples 94
Remarks 98
When To Use 98
Alternatives 98
Examples 98
Remarks 100
Examples 100
Examples 109
Examples 110
Value type - short, int, long (signed 16 bit, 32 bit, 64 bit integers) 110
Value type - ushort, uint, ulong (unsigned 16 bit, 32 bit, 64 bit integers) 111
Remarks 113
Examples 113
Examples 117
Variance 118
Parameters 120
Remarks 120
Examples 120
Introduction 123
Remarks 123
Examples 123
Properties 125
Indexers 125
Methods 126
Operators 126
Limitations 127
Introduction 132
Usage 133
Expressions 138
Basics 146
Limitations 148
Gotchas 148
Introduction 154
Examples 154
Example 154
Limitations 155
References 156
Basics 157
h11 160
References 162
Example 162
Example 163
Example 163
is expression 165
Example 165
Links 167
ValueTask 169
Notes 170
Examples 172
Examples 174
Examples 175
MemoryCache 175
Remarks 176
Examples 176
Examples 181
Syntax 182
Parameters 182
Remarks 182
Examples 182
Syntax 186
Remarks 186
Examples 186
Preconditions 186
Postconditions 187
Invariants 187
Examples 191
Remarks 192
Examples 192
Examples 197
Comments 197
Regions 198
Examples 201
Trimming Unwanted Characters Off the Start and/or End of Strings. 201
String.Trim() 201
Examples 211
Introduction 215
Remarks 215
Examples 215
Chapter 40: Creating a Console Application using a Plain-Text Editor and the C# Compiler ( 225
Examples 225
Creating a Console application using a Plain-Text Editor and the C# Compiler 225
Introduction 227
Syntax 227
Examples 227
How to use own created MessageBox control in another Windows Form application. 229
Chapter 42: Creational Design Patterns 231
Remarks 231
Examples 231
Examples 245
Examples 266
Usage 271
Examples 273
DateTime.Add(TimeSpan) 273
DateTime.AddDays(Double) 273
DateTime.AddHours(Double) 273
DateTime.AddMilliseconds(Double) 273
DateTime.DaysInMonth(Int32,Int32) 274
DateTime.AddYears(Int32) 274
DateTime.Parse(String) 275
DateTime.ParseExact(String,String,IFormatProvider) 278
DateTime.TryParseExact(String,String,IFormatProvider,DateTimeStyles,DateTime) 279
Remarks 282
Summary 282
Examples 283
Remarks 292
Examples 292
Examples 298
Debug.WriteLine 298
Remarks 299
Examples 299
Introduction 302
Syntax 302
Remarks 302
Examples 302
Examples 312
Remarks 313
Examples 313
Introduction 318
Parameters 318
Remarks 318
Examples 319
Examples 327
re-throwing 333
serialization 334
Conclusion 335
Cheatsheet 340
Syntax 344
Parameters 344
Remarks 344
Notes 346
Examples 346
Syntax 351
Parameters 351
Remarks 351
Examples 352
Extension methods can only see public (or internal) members of the extended class 356
Extensions and interfaces together enable DRY code and mixin-like functionality 365
Using Extension methods to build new collection types (e.g. DictList) 369
Introduction 371
Syntax 371
Parameters 371
Remarks 371
Examples 372
Syntax 376
Parameters 376
Examples 376
IsFileReady 377
Syntax 378
Parameters 378
Examples 378
Remarks 381
Examples 381
Examples 383
Immutability 383
Examples 388
Parameters 391
Remarks 391
Examples 391
Generating the same sequence of random numbers over and over again 392
Remarks 394
Examples 394
Usage 398
Output: 398
Syntax 399
Parameters 399
Remarks 399
Examples 399
Covariance 407
Contravariance 408
Invariance 409
Introduction 415
Examples 415
C# Implementation 415
Serialization 416
Deserialization 416
Introduction 418
Remarks 418
Examples 418
Chapter 68: Handling FormatException when converting string to other types 420
Examples 420
Remarks 422
Examples 422
MD5 422
SHA1 423
SHA256 423
SHA384 424
SHA512 424
Chapter 70: How to use C# Structs to create a Union type (Similar to C Unions) 430
Remarks 430
Examples 430
Syntax 433
Remarks 433
Examples 433
Examples 436
Remarks 438
Examples 438
Introduction 442
Remarks 442
Examples 442
IEnumerable 442
Examples 444
Examples 447
Remarks 449
Examples 449
Examples 451
Remarks 454
Examples 454
Requirements 454
Parameters 458
Examples 458
Syntax 460
Remarks 460
Examples 460
Syntax 462
Remarks 462
Examples 462
Remarks 473
Examples 473
Remarks 475
Examples 475
Examples 478
Hint: 480
Note: 480
Remarks 487
Examples 487
Examples 495
Translating a LINQ query to a SQL query 495
Remarks 496
Examples 496
Introduction 499
Remarks 499
Examples 501
stackalloc 501
volatile 502
fixed 504
default 504
readonly 505
as 506
is 507
typeof 508
const 508
namespace 510
continue 511
goto 515
goto as a: 515
Label: 515
enum 516
base 517
foreach 519
params 520
break 521
abstract 522
float 524
double 524
decimal 524
uint 525
this 525
for 526
while 527
return 529
in 529
using 529
sealed 530
sizeof 530
static 531
Drawbacks 533
int 533
long 533
ulong 533
dynamic 534
new 536
lock 540
null 541
internal 542
where 543
The previous examples show generic constraints on a class definition, but constraints can 545
extern 545
bool 546
when 546
unchecked 547
void 547
Important to note that if a condition is met in the above example , the control skips othe 549
do 549
operator 550
struct 551
switch 553
interface 553
unsafe 554
implicit 556
string 557
ushort 557
sbyte 557
var 558
delegate 559
event 560
partial 560
Remarks 563
Examples 563
Passing a Lambda Expression as a Parameter to a Method 563
Remarks 567
Closures 567
Examples 567
Introduction 570
Syntax 570
Remarks 572
Examples 572
Where 572
Range 574
Repeat 575
First() 576
FirstOrDefault() 576
Last() 577
LastOrDefault() 577
Single() 578
SingleOrDefault() 578
Recommendations 579
Except 580
SelectMany 583
All 584
Union 585
JOINS 586
Distinct 588
Basics 591
GroupBy 592
Any 593
1. Empty parameter 593
ToDictionary 594
Aggregate 595
SkipWhile 596
DefaultIfEmpty 596
SequenceEqual 598
Zip 600
TakeWhile 606
Sum 606
ToLookup 606
Reverse 610
OrderBy 613
OrderByDescending 614
Concat 615
Contains 615
Examples 617
Examples 622
Syntax 624
Examples 624
Syntax 627
Remarks 627
Examples 628
Assuming that locking restricts access to the synchronizing object itself 630
Examples 635
break 636
continue 640
Examples 641
Examples 642
Examples 648
Remarks 651
Examples 651
Examples 656
Introduction 659
Syntax 659
Examples 659
Introduction 664
Remarks 664
Examples 664
Capitalization conventions 664
Uppercase 665
Rules 665
Interfaces 666
Namespaces 667
Enums 667
Use a plural name for Enum types that are bit fields 667
Exceptions 668
Syntax 669
Remarks 669
Examples 669
Syntax 673
Remarks 673
Examples 673
Syntax 678
Parameters 678
Remarks 678
Examples 678
Syntax 682
Remarks 682
Examples 682
Examples 685
Examples 687
Syntax 689
Remarks 689
Examples 689
Introduction 691
Examples 691
Classes: 691
Examples 692
Introduction 693
Syntax 693
Parameters 693
Remarks 693
Examples 695
sizeof 700
typeof 706
Examples 711
Remarks 713
Examples 713
Syntax 716
Examples 718
AsOrdered 718
AsUnordered 719
Introduction 720
Syntax 720
Remarks 720
Examples 720
Examples 723
Error handling of specific HTTP response codes (such as 404 Not Found) 724
Sending asynchronous HTTP GET request and reading JSON request 725
Remarks 726
Examples 726
void* 728
Examples 734
Subtyping 736
Syntax 738
Remarks 738
Examples 739
Line 741
Remarks 745
Examples 745
Declaration 749
Examples 751
Introduction 753
Examples 753
Syntax 755
Parameters 755
Examples 755
The following example shows how to open a zip archive and extract all .txt files to a fold 756
Remarks 758
Examples 758
Introduction 765
Remarks 765
Examples 765
Syntax 777
Parameters 777
Remarks 777
Examples 778
Examples 779
RoslynScript 779
CSharpCodeProvider 779
Lazy, thread safe singleton (for .NET 3.5 or older, alternate implementation) 781
Examples 784
Syntax 787
Remarks 787
Examples 787
IsHighResolution 787
Examples 789
Remarks 791
Examples 791
+ Operator 791
Syntax 793
Remarks 793
Examples 793
Syntax 796
Remarks 796
Examples 796
Expressions 796
Examples 800
Introduction 803
Syntax 803
Parameters 803
Remarks 803
Examples 803
Places where String.Format is 'embedded' in the framework 803
Precision 805
ToString() 809
Examples 811
Remarks 813
Examples 813
Introduction 817
Examples 817
Examples 824
Authenticated SSL LDAP connection, SSL cert does not match reverse DNS 824
Remarks 826
Examples 826
Syntax 828
Examples 828
Examples 829
Parallel.ForEach 829
Parallel.For 829
Parallel.Invoke 830
Examples 833
JoinBlock 833
BroadcastBlock 834
WriteOnceBlock 835
BatchedJoinBlock 836
TransformBlock 836
ActionBlock 837
TransformManyBlock 838
BatchBlock 839
BufferBlock 840
Remarks 842
Examples 842
Syntax 852
Remarks 852
Examples 852
Features: 853
Examples 857
Remarks 859
Examples 859
Remarks 861
Examples 861
Remarks 864
Examples 864
Introduction 867
Examples 867
RuntimeSerializer 868
Calling It 869
Examples 872
Creating simple CRUD using SQLite in C# 872
Introduction 877
Syntax 877
Remarks 877
Examples 877
Gotcha: Exception in Dispose method masking other errors in Using blocks 881
Syntax 886
Remarks 886
Introduction 886
Value types exist on the stack, reference types exist on the heap 886
Value types don't change when you change them in a method, reference types do 887
Examples 887
Assignment 890
Syntax 893
Remarks 893
Examples 893
Verbatim strings instruct the compiler to not use character escapes 894
Introduction 896
Examples 896
Examples 899
Remarks 902
Examples 902
Examples 907
Introduction 911
Syntax 911
Remarks 911
Examples 911
Try...finally 916
Credits 921
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: csharp-language
It is an unofficial and free C# Language ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official C# Language.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with C# Language
Remarks
C# is a multi-paradigm, C-descendant programming language from Microsoft. C# is a managed
language that compiles to CIL, intermediate bytecode which can be executed on Windows, Mac
OS X and Linux.
Versions 1.0, 2.0 and 5.0 were standardized by ECMA (as ECMA-334), and standardization efforts
for modern C# are underway.
Versions
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
Examples
Creating a new console application (Visual Studio)
https://riptutorial.com/ 2
System.Console.WriteLine("Hello, World!");
6. In the toolbar, click Debug -> Start Debugging or hit F5 or ctrl + F5 (running without
debugger) to run the program.
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.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.
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
https://riptutorial.com/ 3
HelloWorld 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):
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
Hello, world!
You may also double click the executable and launch a new console window with the message "
Hello, world!"
https://riptutorial.com/ 4
Creating a new project in Visual Studio (console application) and Running it in
Debug mode
1. 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.
https://riptutorial.com/ 5
5. After selecting Console Application, Enter a name for your project, and a location to save
and press OK. Don't worry about the Solution name.
6. Project created. The newly created project will look similar to:
https://riptutorial.com/ 6
https://riptutorial.com/ 7
(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.)
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:
https://riptutorial.com/ 8
9. 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.
First install Mono by going through the install instructions for the platform of your choice as
described in their installation section.
After installation is done, create a text file, name it HelloWorld.cs and copy the following content
into it:
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:
https://riptutorial.com/ 9
mcs -out:HelloWorld.exe HelloWorld.cs
mono HelloWorld.exe
Hello, world!
Press any key to exit..
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.
1. Create a new directory with mkdir hello_world and change into the newly created directory
with cd hello_world.
• hello_world.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
</Project>
• Program.cs
using System;
namespace hello_world
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
https://riptutorial.com/ 10
}
}
}
4. 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.
https://riptutorial.com/ 11
LinqPad is a great tool that allows you to learn and test features of .Net languages (C#, F# and
VB.Net.)
1. Install LinqPad
https://riptutorial.com/ 12
4. Type the following code and hit run (F5)
5. You should see "Hello World" printed out in the results screen.
6. 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.
https://riptutorial.com/ 13
Notes:
1. If you click on "IL", you can inspect the IL code that your .net code generates. This is a great
learning tool.
https://riptutorial.com/ 14
2. 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.
https://riptutorial.com/ 15
4. Click .NET → Console Project and choose C#.
5. Click Next to proceed.
https://riptutorial.com/ 16
6. Enter the Project Name and Browse... for a Location to Save and then click Create.
https://riptutorial.com/ 17
7. The newly created project will look similar to:
https://riptutorial.com/ 18
8. This is the code in the Text Editor:
using System;
namespace FirstCsharp
{
public class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
}
}
https://riptutorial.com/ 19
}
9. To run the code, press F5 or click the Play Button as shown below:
https://riptutorial.com/ 20
Read Getting started with C# Language online: https://riptutorial.com/csharp/topic/15/getting-
started-with-csharp-language
https://riptutorial.com/ 21
Chapter 2: .NET Compiler Platform (Roslyn)
Examples
Create workspace from MSBuild project
To load existing code to the workspace, compile and report errors. Afterwards the code will be
located in memory. From here, both the syntactic and semantic side will be available to work with.
Syntax tree
A Syntax Tree is an immutable data structure representing the program as a tree of names,
commands and marks (as previously configured in the editor.)
Every type of C# construct with a corresponding type will exist in the syntax tree. To quickly find
specific types, use the Syntax Visualizer window from Visual Studio. This will interpret the current
opened document as a Roslyn syntax tree.
Semantic model
https://riptutorial.com/ 22
A Semantic Model offers a deeper level of interpretation and insight of code compare to a syntax
tree. Where syntax trees can tell the names of variables, semantic models also give the type and
all references. Syntax trees notice method calls, but semantic models give references to the
precise location the method is declared (after overload resolution has been applied.)
Console.WriteLine(variableSymbol.Type);
// => "Microsoft.CodeAnalysis.SyntaxNode"
This outputs a list of local variables using a syntax tree. Then it consults the semantic model to get
the full type name and find all references of every variable.
https://riptutorial.com/ 23
Chapter 3: Access Modifiers
Remarks
If the access modifier is omitted,
Access modifiers on setters or getters of properties can only restrict access, not widen it: public
string someProperty {get; private set;}
Examples
public
The public keyword makes a class (including nested classes), property, method or field available
to every consumer:
private
The private keyword marks properties, methods, fields and nested classes for use inside the class
only:
https://riptutorial.com/ 24
private class Baz
{
public string Value { get; set; }
}
internal
The internal keyword makes a class (including nested classes), property, method or field available
to every consumer in the same assembly:
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")]
protected
The protected keyword marks field, methods properties and nested classes for use inside the
https://riptutorial.com/ 25
same class and derived classes only:
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
https://riptutorial.com/ 26
var myPublicProperty = foo.MyPublicProperty;
var myProtectedInternalProperty = foo.MyProtectedInternalProperty;
var myProtectedInternalNestedInstance =
new Foo.MyProtectedInternalNestedClass();
}
}
Assembly 2
void MyMethod2()
{
Foo foo = new Foo();
var myPublicProperty = foo.MyPublicProperty;
// Compile Error
var myProtectedInternalProperty = foo.MyProtectedInternalProperty;
// Compile Error
var myProtectedInternalNestedInstance =
new Foo.MyProtectedInternalNestedClass();
}
// 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();
}
}
https://riptutorial.com/ 27
Access Modifiers Diagrams
Here are all access modifiers in venn diagrams, from more limiting to more accessible:
private
internal
protected
protected internal
https://riptutorial.com/ 28
Access Modifier Diagram
public
https://riptutorial.com/ 29
Chapter 4: Access network shared folder with
username and password
Introduction
Accessing network share file using PInvoke.
Examples
Code to access network shared file
if (result != 0)
{
throw new Win32Exception(result);
}
}
~NetworkConnection()
{
Dispose(false);
}
https://riptutorial.com/ 30
}
[DllImport("mpr.dll")]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
[DllImport("mpr.dll")]
private static extern int WNetCancelConnection2(string name, int flags,
bool force);
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public ResourceScope Scope;
public ResourceType ResourceType;
public ResourceDisplaytype DisplayType;
public int Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
https://riptutorial.com/ 31
Read Access network shared folder with username and password online:
https://riptutorial.com/csharp/topic/9627/access-network-shared-folder-with-username-and-
password
https://riptutorial.com/ 32
Chapter 5: Accessing Databases
Examples
ADO.NET Connections
ADO.NET Connections are one of the simplest ways to connect to a database from a C#
application. They rely on the use of a provider and a connection string that points to your database
to perform queries against.
All of these are commonly used to access data through C# and will be commonly encountered
throughout building data-centric applications. Many other classes that are not mentioned that
implement the same FooConnection,FooCommand,FooDataReader classes can be expected to behave
the same way.
https://riptutorial.com/ 33
Or if you were just performing a simple update and didn't require a reader, the same basic concept
would apply :
You can even program against a set of common interfaces and not have to worry about the
provider specific classes. The core interfaces provided by ADO.NET are:
Entity Framework exposes abstraction classes that are used to interact with underlying databases
in the form of classes like DbContext. These contexts generally consist of DbSet<T> properties that
expose the available collections that can be queried :
https://riptutorial.com/ 34
public class ExampleContext: DbContext
{
public virtual DbSet<Widgets> Widgets { get; set; }
}
The DbContext itself will handle making the connections with the databases and will generally read
the appropriate Connection String data from a configuration to determine how to establish the
connections :
Entity Framework also provides an extensive change-tracking system that can be used to handle
updating entries within your database by simply calling the SaveChanges() method to push changes
to the database :
Connection Strings
A Connection String is a string that specifies information about a particular data source and how to
go about connecting to it by storing credentials, locations, and other information.
https://riptutorial.com/ 35
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;
<connectionStrings>
<add name="WidgetsContext" providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=Widgets;Integrated Security=True;"/>
</connectionStrings>
<connectionStrings>
<add name="WidgetsContext" providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=Widgets;Integrated Security=SSPI;"/>
</connectionStrings>
This will allow your application to access the connection string programatically through
WidgetsContext. Although both Integrated Security=SSPI and Integrated Security=True perform the
same function;Integrated Security=SSPI is preferred since works with both SQLClient & OleDB
provider where as Integrated Security=true throws an exception when used with the OleDb
provider.
https://riptutorial.com/ 36
Chapter 6: Action Filters
Examples
Custom Action Filters
We write custom action filters for various reasons. We may have a custom action filter for logging,
or for saving data to database before any action execution. We could also have one for fetching
data from the database and setting it as the global values of the application.
1. Create a class
2. Inherit it from ActionFilterAttribute class
using System;
using System.Diagnostics;
using System.Web.Mvc;
namespace WebApplication1
{
https://riptutorial.com/ 37
Debug.WriteLine(message, "Action Filter Log");
base.OnActionExecuting(filterContext);
}
}
}
https://riptutorial.com/ 38
Chapter 7: Aliases of built-in types
Examples
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.
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:
https://riptutorial.com/ 39
Read Aliases of built-in types online: https://riptutorial.com/csharp/topic/1862/aliases-of-built-in-
types
https://riptutorial.com/ 40
Chapter 8: An overview of c# collections
Examples
HashSet
HashSet.Contains uses a hash table, so that lookups are extremely fast, regardless of the number
of items in the collection.
SortedSet
// add something
// note that we add 2 before we add 1
mySet.Add(2);
mySet.Add(1);
// output:
// 1
// 2
T[ ] (Array of T)
https://riptutorial.com/ 41
// output:
// one
// two
// output:
// something else
// two
List
List<T> is a list of a given type. Items can be added, inserted, removed and addressed by index.
using System.Collections.Generic;
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.
Dictionary
Dictionary<TKey, TValue> is a map. For a given key there can be one value in the dictionary.
using System.Collections.Generic;
// 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
}
https://riptutorial.com/ 42
// Adding and changing data
people["John"] = 40; // Overwriting values this way is ok
people.Add("John", 40); // Throws ArgumentException since "John" already exists
Stack
// 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
LinkedList
https://riptutorial.com/ 43
// initialize a LinkedList of integers
LinkedList list = new LinkedList<int>();
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
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.
Queue
https://riptutorial.com/ 44
Chapter 9: Anonymous types
Examples
Creating an anonymous type
Since anonymous types are not named, variables of those types must be implicitly typed (var).
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.
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.
Conversely, dynamic has dynamic type checking, opting for runtime errors, instead of compile-time
errors.
https://riptutorial.com/ 45
Generic methods with anonymous types
Generic methods allow the use of anonymous types through type inference.
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.
In the case of List<T>, implicitly typed arrays may be converted to a List<T> through the ToList
LINQ method:
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.
https://riptutorial.com/ 46
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.
https://riptutorial.com/ 47
Chapter 10: Arrays
Syntax
• Declaring an array:
<type>[] <name>;
<name>[i]
<name>.Length
Remarks
In C#, an array is a reference type, which means it is nullable.
An array has a fixed length, which means you cant .Add() to it or .Remove() from it. In order to use
these, you would need a dynamic array - List or ArrayList.
Examples
https://riptutorial.com/ 48
Array covariance
This conversion is not type-safe. The following code will raise a runtime exception:
// Get
Console.WriteLine(arr[2]); // 20
// Set
arr[2] = 100;
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:
Indices in C# are zero-based. The indices of the array above will be 0-9. For example:
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.
An array can also be created and initialized with custom values using collection initialization
syntax:
https://riptutorial.com/ 49
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):
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 };
using foreach:
unsafe
{
int length = arr.Length;
fixed (int* p = arr)
{
int* pInt = p;
while (length-- > 0)
{
Console.WriteLine(*pInt);
pInt++;// move pointer to next element
}
}
}
https://riptutorial.com/ 50
Output:
1
6
3
3
9
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[4, 2] { {1, 1}, {2, 2}, {3, 3}, {4, 4} };
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.
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.
The second [] is initialized without a number. To initialize the sub arrays, you would need to do
that separately:
https://riptutorial.com/ 51
Getting/Setting values
Now, getting one of the subarrays is easy. Let's print all the numbers of the 3rd column of a:
a[<row_number>][<column_number>]
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.
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[][,,,,][,,]"
https://riptutorial.com/ 52
{
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;
}
}
return false;
}
/// Sample
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:
https://riptutorial.com/ 53
int[] intArray = Enumerable.Repeat(100, 5).ToArray();
Copying arrays
Copying a partial array with the static Array.Copy() method, beginning at index 0 in both, source
and destination:
Copying the whole array with the CopyTo() instance method, beginning at index 0 of the source and
the specified index in the destination:
Both CopyTo and Clone perform shallow copy which means the contents contains references to the
same object as the elements in the original array.
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.
https://riptutorial.com/ 54
Usage:
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:
This will generate an array that contains 10 integer squares starting at 4: [4, 9, 16, ..., 100, 121]
.
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.
int[] arr1 = { 3, 5, 7 };
int[] arr2 = { 3, 5, 7 };
bool result = arr1.SequenceEqual(arr2);
Console.WriteLine("Arrays equal? {0}", result);
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.
https://riptutorial.com/ 55
The IEnumerable<> support means arrays can be queried with LINQ, for example arr1.Select(i =>
10 * i).
https://riptutorial.com/ 56
Chapter 11: ASP.NET Identity
Introduction
Tutorials concerning asp.net Identity such as user management, role management, creating
tokens and more.
Examples
How to implement password reset token in asp.net identity using user
manager.
1. Create a new folder called MyClasses and create and add the following class
public GmailEmailService() :
base(ConfigurationManager.AppSettings["GmailHost"],
Int32.Parse(ConfigurationManager.AppSettings["GmailPort"]))
{
//Get values from web.config file:
this.UserName = ConfigurationManager.AppSettings["GmailUserName"];
this.EnableSsl = Boolean.Parse(ConfigurationManager.AppSettings["GmailSsl"]);
this.UseDefaultCredentials = false;
this.Credentials = new System.Net.NetworkCredential(this.UserName,
ConfigurationManager.AppSettings["GmailPassword"]);
}
}
email.IsBodyHtml = true;
3. Add your credentials to the web.config. I did not use gmail in this portion because the use of
gmail is blocked in my workplace and it still works perfectly.
https://riptutorial.com/ 57
<add key="GmailUserName" value="[email protected]"/>
<add key="GmailPassword" value="yourPassword"/>
<add key="GmailHost" value="yourServer"/>
<add key="GmailPort" value="yourPort"/>
<add key="GmailSsl" value="chooseTrueOrFalse"/>
<!--Smptp Server (confirmations emails)-->
4. Make necessary changes to your Account Controller. Add the following highlighted code.
https://riptutorial.com/ 58
https://riptutorial.com/ 59
Compile then run. Cheers!
https://riptutorial.com/ 60
Chapter 12: AssemblyInfo.cs Examples
Remarks
The filename AssemblyInfo.cs is used by convention as the source file where developers place
metadata attributes that describe the entire assembly they are building.
Examples
[AssemblyTitle]
[assembly: AssemblyTitle("MyProduct")]
[AssemblyProduct]
This attribute is used to describe the product that this particular assembly is for. Multiple
assemblies can be components of the same product, in which case they can all share the same
value for this attribute.
[assembly: AssemblyProduct("MyProduct")]
Having a global allows for better DRYness, you need only put values that are different into
AssemblyInfo.cs for projects that have variance. This use assumes your product has more than
one visual studio project.
GlobalAssemblyInfo.cs
using System.Reflection;
using System.Runtime.InteropServices;
//using Stackoverflow domain as a made up example
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4e4f2d33-aaab-48ea-a63d-1f0a8e3c935f")]
[assembly: ComVisible(false)] //not going to expose ;)
https://riptutorial.com/ 61
// dynamically generate this file
// Major Version - Year 6 being 2016
// Minor Version - The month
// Day Number - Day of month
// Revision - Build number
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: [assembly: AssemblyVersion("year.month.day.*")]
[assembly: AssemblyVersion("2016.7.00.00")]
[assembly: AssemblyFileVersion("2016.7.27.3839")]
//then the following might be put into a separate Assembly file per project, e.g.
[assembly: AssemblyTitle("Stackoveflow.Redis")]
You can add the GlobalAssemblyInfo.cs to the local project using the following procedure:
[AssemblyVersion]
[assembly: AssemblyVersion("1.0.*")]
The * character is used to auto-increment a portion of the version automatically every time you
compile (often used for the "build" number)
Using .NET's rich reflection APIs, you can gain access to an assembly's metadata. For example,
you can get this assembly's title attribute with the following code
using System.Linq;
using System.Reflection;
...
Automated versioning
Your code in source control has version numbers either by default (SVN ids or Git SHA1 hashes)
or explicitly (Git tags). Rather than manually updating versions in AssemblyInfo.cs you can use a
build time process to write the version from your source control system into your AssemblyInfo.cs
https://riptutorial.com/ 62
files and thus onto your assemblies.
The GitVersionTask or SemVer.Git.Fody NuGet packages are examples of the above. To use
GitVersionTask, for instance, after installing the package in your project remove the
Assembly*Version attributes from your AssemblyInfo.cs files. This puts GitVersionTask in charge of
versioning your assemblies.
Note that Semantic Versioning is increasingly the de facto standard so these methods recommend
using source control tags that follow SemVer.
Common fields
It's good practice to complete your AssemblyInfo's default fields. The information may be picked
up by installers and will then appear when using Programs and Features (Windows 10) to uninstall
or change a program.
'AssemblyTitle' becomes the 'File description' when examining the DLL's Properties Details tab.
[AssemblyConfiguration]
AssemblyConfiguration: The AssemblyConfiguration attribute must have the configuration that was
used to build the assembly. Use conditional compilation to properly include different assembly
configurations. Use the block similar to the example below. Add as many different configurations
as you commonly use.
#if (DEBUG)
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
[InternalsVisibleTo]
If you want to make internal classes or functions of an assembly accessable from another
assembly you declare this by InternalsVisibleTo and the assembly name that is allowed to access.
In this example code in the assembly MyAssembly.UnitTests is allowed to call internal elements
from MyAssembly.
https://riptutorial.com/ 63
[assembly: InternalsVisibleTo("MyAssembly.UnitTests")]
This is especially useful for unit testing to prevent unnecessary public declarations.
[AssemblyKeyFile]
Whenever we want our assembly to install in GAC then it is must to have a strong name. For
strong naming assembly we have to create a public key. To generate the .snk file.
once the keyFileName.snk is created at specified directory then give refernce in your project . give
AssemblyKeyFileAttribute attribute the path to snk file to generate the key when we build our class
library.
[assembly: AssemblyKeyFile(@"c:\Directory_Name\KeyFileName.snk")]
Thi will create a strong name assembly after build. After creating your strong name assembly you
can then install it in GAC
Happy Coding :)
https://riptutorial.com/ 64
Chapter 13: Async/await, Backgroundworker,
Task and Thread Examples
Remarks
To run any of these examples just call them like that:
Examples
ASP.NET Configure Await
When ASP.NET handles a request, a thread is assigned from the thread pool and a request
context is created. The request context contains information about the current request which can
be accessed through the static HttpContext.Current property. The request context for the request is
then assigned to the thread handling the request.
When execution reaches await, the thread handling a request is returned to the thread pool while
the asynchronous method runs and the request context is free for another thread to use.
When the task completes the thread pool assigns another thread to continue execution of the
request. The request context is then assigned to this thread. This may or may not be the original
thread.
Blocking
When the result of an async method call is waited for synchronously deadlocks can arise. For
example the following code will result in a deadlock when IndexSync() is called:
https://riptutorial.com/ 65
public async Task<ActionResult> Index()
{
// Execution on the initially assigned thread
List<Product> products = await dbContext.Products.ToListAsync();
return result;
}
This is because, by default the awaited task, in this case db.Products.ToListAsync() will capture the
context (in the case of ASP.NET the request context) and try to use it once it has completed.
When the entire call stack is asynchronous there is no problem because, once await is reached
the original thread is release, freeing the request context.
When we block synchronously using Task.Result or Task.Wait() (or other blocking methods) the
original thread is still active and retains the request context. The awaited method still operates
asynchronously and once the callback tries to run, i.e. once the awaited task has returned, it
attempts to obtain the request context.
Therefore the deadlock arises because while the blocking thread with the request context is
waiting for the asynchronous operation to complete, the asynchronous operation is trying to obtain
the request context in order to complete.
ConfigureAwait
By default calls to an awaited task will capture the current context and attempt to resume
execution on the context once complete.
// Execution resumes on a "random" thread from the pool without the original request
context
return View(products);
}
https://riptutorial.com/ 66
// Block waiting for the result synchronously
ActionResult result = Task.Result;
return result;
}
This can avoid deadlocks when it is necessary to block on asynchronous code, however this
comes at the cost of losing the context in the continuation (code after the call to await).
In ASP.NET this means that if your code following a call to await someTask.ConfigureAwait(false);
attempts to access information from the context, for example HttpContext.Current.User then the
information has been lost. In this case the HttpContext.Current is null. For example:
return View();
}
If ConfigureAwait(true) is used (equivalent to having no ConfigureAwait at all) then both user and
user2 are populated with the same data.
For this reason it is often recommended to use ConfigureAwait(false) in library code where the
context is no longer used.
Async/await
See below for a simple example of how to use async/await to do some time intensive stuff in a
background process while maintaining the option of doing some other stuff that do not need to wait
on the time intensive stuff to complete.
However, if you need to work with the result of the time intensive method later, you can do this by
awaiting the execution.
https://riptutorial.com/ 67
Console.WriteLine("Count: " + x);
}
BackgroundWorker
See below for a simple example of how to use a BackgroundWorker object to perform time-intensive
operations in a background thread.
1. Define a worker method that does the time-intensive work and call it from an event handler
for the DoWork event of a BackgroundWorker.
2. Start the execution with RunWorkerAsync. Any argument required by the worker method
attached to DoWork can be passed in via the DoWorkEventArgs parameter to RunWorkerAsync.
In addition to the DoWork event the BackgroundWorker class also defines two events that should be
used for interacting with the user interface. These are optional.
• The RunWorkerCompleted event is triggered when the DoWork handlers have completed.
• The ProgressChanged event is triggered when the ReportProgress method is called.
https://riptutorial.com/ 68
}
Task
See below for a simple example of how to use a Task to do some time intensive stuff in a
background process.
All you need to do is wrap your time intensive method in a Task.Run() call.
https://riptutorial.com/ 69
// return something as a "result"
return new Random().Next(100);
}
Thread
See below for a simple example of how to use a Thread to do some time intensive stuff in a
background process.
As you can see we can not return a value from our TimeIntensiveMethod because Thread expects a
void Method as its parameter.
To get a return value from a Thread use either an event or the following:
int ret;
Thread t= new Thread(() =>
{
Console.WriteLine("Start TimeintensiveMethod.");
https://riptutorial.com/ 70
t.Start();
t.Join(1000);
Console.Writeline("Count: " + ret);
In certain cases (e.g. logging) it might be useful to run task and do not await for the result. The
following extension allows to run task and continue execution of the rest code:
The result is awaited only inside the extension method. Since async/await is used, it is possible to
catch an exception and call an optional method for handling it.
var task = Task.FromResult(0); // Or any other task from e.g. external lib.
task.RunAndForget(
e =>
{
// Something went wrong, handle it.
});
https://riptutorial.com/ 71
Chapter 14: Async-Await
Introduction
In C#, a method declared async won't block within a synchronous process, in case of you're using
I/O based operations (e.g. web access, working with files, ...). The result of such async marked
methods may be awaited via the use of the awaitkeyword.
Remarks
An async method can return void, Task or Task<T>.
The return type Task will wait for the method to finish and the result will be void. Task<T> will return
a value from type T after the method completes.
async methods should return Task or Task<T>, as opposed to void, in almost all circumstances. async
void methods cannot be awaited, which leads to a variety of problems. The only scenario where an
async should return void is in the case of an event handler.
async/await works by transforming your async method into a state machine. It does this by creating
a structure behind the scenes which stores the current state and any context (like local variables),
and exposes a MoveNext() method to advance states (and run any associated code) whenever an
awaited awaitable completes.
Examples
Simple consecutive calls
The main thing to note here is that while every await-ed method is called asynchronously - and for
the time of that call the control is yielded back to the system - the flow inside the method is linear
and does not require any special treatment due to asynchrony. If any of the methods called fail,
the exception will be processed "as expected", which in this case means that the method
execution will be aborted and the exception will be going up the stack.
Try/Catch/Finally
6.0
https://riptutorial.com/ 72
As of C# 6.0, the await keyword can now be used within a catch and finally block.
try {
var client = new AsyncClient();
await client.DoSomething();
} catch (MyException ex) {
await client.LogExceptionAsync();
throw;
} finally {
await client.CloseAsync();
}
5.06.0
Prior to C# 6.0, you would need to do something along the lines of the following. Note that 6.0 also
cleaned up the null checks with the Null Propagating operator.
AsynClient client;
MyException caughtException;
try {
client = new AsyncClient();
await client.DoSomething();
} catch (MyException ex) {
caughtException = ex;
}
if (client != null) {
if (caughtException != null) {
await client.LogExceptionAsync();
}
await client.CloseAsync();
if (caughtException != null) throw caughtException;
}
Please note that if you await a task not created by async (e.g. a task created by Task.Run), some
debuggers may break on exceptions thrown by the task even when it is seemingly handled by the
surrounding try/catch. This happens because the debugger considers it to be unhandled with
respect to user code. In Visual Studio, there is an option called "Just My Code", which can be
disabled to prevent the debugger from breaking in such situations.
The web.config system.web.httpRuntime must target 4.5 to ensure the thread will renter the
request context before resuming your async method.
Async and await have undefined behavior on ASP.NET prior to 4.5. Async / await will resume on
an arbitrary thread that may not have the request context. Applications under load will randomly
fail with null reference exceptions accessing the HttpContext after the await. Using
HttpContext.Current in WebApi is dangerous because of async
https://riptutorial.com/ 73
Concurrent calls
It is possible to await multiple calls concurrently by first invoking the awaitable tasks and then
awaiting them.
await firstTask;
await secondTask;
}
Alternatively, Task.WhenAll can be used to group multiple tasks into a single Task, which completes
when all of its passed tasks are complete.
await Task.WhenAll(tasks);
To get results from a task after awaiting multiple tasks with Task.WhenAll, simply await the task
again. Since the task is already completed it will just return the result back
Also, the Task.WhenAny can be used to execute multiple tasks in parallel, like the Task.WhenAll
above, with the difference that this method will complete when any of the supplied tasks will be
completed.
https://riptutorial.com/ 74
var secondTask = TaskOperation("#secondTask executed");
var thirdTask = TaskOperation("#thirdTask executed");
await Task.WhenAny(firstTask, secondTask, thirdTask);
}
The Task returned by RunConcurrentTasksWhenAny will complete when any of firstTask, secondTask, or
thirdTask completes.
The asynchronous method in which await is used must be modified by the async
keyword.
The opposite is not always true: you can mark a method as async without using await in its body.
What await actually does is to suspend execution of the code until the awaited task completes; any
task can be awaited.
Note: you cannot await for async method which returns nothing (void).
Actually, the word 'suspends' is a bit misleading because not only the execution stops, but the
thread may become free for executing other operations. Under the hood, await is implemented by
a bit of compiler magic: it splits a method into two parts - before and after await. The latter part is
executed when the awaited task completes.
If we ignore some important details, the compiler roughly does this for you:
becomes:
https://riptutorial.com/ 75
Any usual method can be turned into async in the following way:
This can be advantageous when you need to execute a long running method on the UI thread
without freezing the UI.
But there is a very important remark here: Asynchronous does not always mean concurrent
(parallel or even multi-threaded). Even on a single thread, async-await still allows for
asynchronous code. For example, see this custom task scheduler. Such a 'crazy' task scheduler
can simply turn tasks into functions which are called within message loop processing.
We need to ask ourselves: What thread will execute the continuation of our method
DoIt_Continuation?
By default the await operator schedules the execution of continuation with the current
Synchronization context. It means that by default for WinForms and WPF continuation runs in the
UI thread. If, for some reason, you need to change this behavior, use method
Task.ConfigureAwait():
Methods that perform asynchronous operations don't need to use await if:
If GetByKeyAsync has the same signature as GetUserAsync (returning a Task<User>), the method can
be simplified:
return dataStore.GetByKeyAsync(lookupKey);
}
In this case, the method doesn't need to be marked async, even though it's preforming an
https://riptutorial.com/ 76
asynchronous operation. The Task returned by GetByKeyAsync is passed directly to the calling
method, where it will be awaited.
Important: Returning the Task instead of awaiting it, changes the exception behavior of the
method, as it won't throw the exception inside the method which starts the task but in the method
which awaits it.
This will improve performance as it will save the compiler the generation of an extra async state
machine.
It is a bad practice to block on async calls as it can cause deadlocks in environments that have a
synchronization context. The best practice is to use async/await "all the way down." For example,
the following Windows Forms code causes a deadlock:
https://riptutorial.com/ 77
bool result = TryThis().Result;
// Never actually gets here
Trace.TraceInformation("Done with result");
}
Essentially, once the async call completes, it waits for the synchronization context to become
available. However, the event handler "holds on" to the synchronization context while it's waiting
for the TryThis() method to complete, thus causing a circular wait.
Note: event handlers are the only place where async void should be used (because you can't await
an async void method).
https://riptutorial.com/ 78
// Do other work
}
The primary purpose of async/await is to allow the machine to do additional work - for example, to
allow the calling thread to do other work while it's waiting for a result from some I/O operation. In
this case, the calling thread is never allowed to do more work than it would have been able to do
otherwise, so there's no performance gain over simply calling MethodA(), MethodB(), and MethodC()
synchronously.
https://riptutorial.com/ 79
Chapter 15: Asynchronous Socket
Introduction
By using asynchronous sockets a server can listening for incoming connections and do some
other logic in the mean time in contrast to synchronous socket when they are listening they block
the main thread and the application is becoming unresponsive an will freeze until a client
connects.
Remarks
Socket and network
How to access a Server outside my own network? This is a common question and when it is
asked is mostly flagged as of topic.
Server Side
On the network of your server you need to port forward your router to your server.
local IP = 192.168.1.115
Client Side
The only thing you need to change is the IP. You don't want to connect to your loopback address
but to the public IP from the network your server is running on. This IP you can get here.
So now you create a request on this endpoint : 10.10.10.10:1234 if you did property port forward
your router your server and client will connect without any problem.
If you want to connect to a local IP you won't have to portforwart just change the loopback address
to 192.168.1.178 or something like that.
Sending data:
Data is send in byte array. You need to pack you data into an byte array and unpack it on the
other side.
If you are familiar with socket you also can try to encrypt your byte array before sending. This will
https://riptutorial.com/ 80
prevent anyone from stealing your package.
Examples
Asynchronous Socket (Client / Server) example.
Start of with creating an server that will handle clients that connect, and requests that will be send.
So create an Listener Class that will handle this.
class Listener
{
public Socket ListenerSocket; //This is the socket that will listen to any incoming
connections
public short Port = 1234; // on this port we will listen
public Listener()
{
ListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
}
}
First we need to initialize the Listener socket where we can listen on for any connections. We are
going to use an Tcp Socket that is why we use SocketType.Stream. Also we specify to witch port
the server should listen to
1. ListenerSocket.Bind();
This method binds the socket to an IPEndPoint. This class contains the host and local or
remote port information needed by an application to connect to a service on a host.
2. ListenerSocket.Listen(10);
The backlog parameter specifies the number of incoming connections that can be queued for
acceptance.
3. ListenerSocket.BeginAccept();
The server will start listening for incoming connections and will go on with other logic. When
there is an connection the server switches back to this method and will run the
AcceptCallBack methodt
https://riptutorial.com/ 81
{
try
{
MessageBox.Show($"Listening started port:{Port} protocol type:
{ProtocolType.Tcp}");
ListenerSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
ListenerSocket.Listen(10);
ListenerSocket.BeginAccept(AcceptCallback, ListenerSocket);
}
catch(Exception ex)
{
throw new Exception("listening error" + ex);
}
}
1. ListenerSocket.EndAccept()
We started the callback with Listener.BeginAccept() end now we have to end that call back.
The EndAccept() method accepts an IAsyncResult parameter, this will store the state of the
asynchronous method, From this state we can extract the socket where the incoming
connection was coming from.
2. ClientController.AddClient()
With the socket we got from EndAccept() we create an Client with an own made method
(code ClientController below server example).
3. ListenerSocket.BeginAccept()
We need to start listening again when the socket is done with handling the new connection.
Pass in the method who will catch this callback. And also pass int the Listener socket so we
can reuse this socket for upcoming connections.
ListenerSocket.BeginAccept(AcceptCallback, ListenerSocket);
}
catch (Exception ex)
{
throw new Exception("Base Accept error"+ ex);
}
}
Now we have an Listening Socket but how do we receive data send by the client that is what the
https://riptutorial.com/ 82
next code is showing.
First of create a receive class with a constructor that takes in a Socket as parameter:
In the next method we first start off with giving the buffer a size of 4 bytes (Int32) or package
contains to parts {lenght, actual data}. So the first 4 bytes we reserve for the lenght of the data the
rest for the actual data.
Next we use BeginReceive() method. This method is used to start receiving from connected
clients and when it will receive data it will run the ReceiveCallback function.
https://riptutorial.com/ 83
the socket.
StartReceiving();
}
else
{
Disconnect();
}
}
catch
{
// if exeption is throw check if socket is connected because than you can
startreive again else Dissconect
if (!_receiveSocket.Connected)
{
Disconnect();
}
else
{
StartReceiving();
}
}
}
So we've setup a server that can receive and listen for incoming connections. When a clients
connect it will be added to a list of clients and every client has his own receive class. To make the
server listen:
class Client
{
public Socket _socket { get; set; }
public ReceivePacket Receive { get; set; }
public int Id { get; set; }
https://riptutorial.com/ 84
{
public static List<Client> Clients = new List<Client>();
Connecting to server
First of all we want to create a class what connects to the server te name we give it is: Connector:
class Connector
{
private Socket _connectingSocket;
}
3. Every loop it is just holding the Thread for 1 second we don't want to DOS the server XD
4. With Connect() it will try to connect to the server. If it fails it will throw an exception but the
wile will keep the program connecting to the server. You can use a Connect CallBack
method for this, but I'll just go for calling a method when the Socket is connected.
5. Notice the Client is now trying to connect to your local pc on port 1234.
while (!_connectingSocket.Connected)
{
Thread.Sleep(1000);
try
{
_connectingSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"),
1234));
}
https://riptutorial.com/ 85
catch { }
}
SetupForReceiveing();
}
}
So now we have an almost finish or Socket application. The only thing that we don't have jet is a
Class for sending a message to the server.
Finaly crate two buttons one for connect and the other for sending a message:
https://riptutorial.com/ 86
tpp.TryToConnect();
}
Notice
The Receive Class from the server is the same as the receive class from the client.
Conclusion
You now have a server and a client. You can work this basic example out. For example make it
that the server also can receive files or other tings. Or send a message to the client. In the server
you got a list of client so when you receive something you will know from with client it came from.
Final result:
https://riptutorial.com/ 87
Read Asynchronous Socket online: https://riptutorial.com/csharp/topic/9638/asynchronous-socket
https://riptutorial.com/ 88
Chapter 16: Attributes
Examples
Creating a custom attribute
Using an attribute
Reading an attribute
Method GetCustomAttributes returns an array of custom attributes applied to the member. After
retrieving this array you can search for one or more specific attributes.
https://riptutorial.com/ 89
foreach(var attribute in typeof(MyClass).GetCustomAttributes()) {
Console.WriteLine(attribute.GetType());
}
GetCustomAttribute also has generic signature to specify type of attribute to search for.
Boolean argument inherit can be passed to both of those methods. If this value set to true the
ancestors of element would be also to inspected.
DebuggerDisplay Attribute
Adding the DebuggerDisplay Attribute will change the way the debugger displays the class when it is
hovered over.
Expressions that are wrapped in {} will be evaluated by the debugger. This can be a simple
property like in the following sample or more complex logic.
[DebuggerDisplay("{StringProperty} - {IntProperty}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
Adding ,nq before the closing bracket removes the quotes when outputting a string.
[DebuggerDisplay("{StringProperty,nq} - {IntProperty}")]
Even though general expressions are allowed in the {} they are not recommended. The
DebuggerDisplay attribute will be written into the assembly metadata as a string. Expressions in {}
are not checked for validity. So a DebuggerDisplay attribute containing more complex logic than i.e.
some simple arithmetic might work fine in C#, but the same expression evaluated in VB.NET will
https://riptutorial.com/ 90
probably not be syntactically valid and produce an error while debugging.
A way to make DebuggerDisplay more language agnostic is to write the expression in a method or
property and call it instead.
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
One might want DebuggerDisplayto output all or just some of the properties and when debugging
and inspecting also the type of the object.
The example below also surrounds the helper method with #if DEBUG as DebuggerDisplay is used in
debugging environments.
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
public int ObjectId { get; set; }
public string StringProperty { get; set; }
public int IntProperty { get; set; }
#if DEBUG
private string DebuggerDisplay()
{
return
$"ObjectId:{this.ObjectId}, StringProperty:{this.StringProperty},
Type:{this.GetType()}";
}
#endif
}
Caller info attributes can be used to pass down information about the invoker to the invoked
method. The declaration looks like this:
using System.Runtime.CompilerServices;
https://riptutorial.com/ 91
And the invocation looks like this:
Notice that only the first parameter is passed explicitly to the LogException method whereas the rest
of them will be provided at compile time with the relevant values.
The callerMemberName parameter will receive the value "Save" - the name of the calling method.
The callerLineNumber parameter will receive the number of whichever line the LogException method
call is written on.
And the 'callerFilePath' parameter will receive the full path of the file Save method is declared in.
There is no simple way to obtain attributes from an interface, since classes does not inherit
attributes from an interface. Whenever implementing an interface or overriding members in a
derived class, you need to re-declare the attributes. So in the example below output would be True
in all three cases.
using System;
using System.Linq;
using System.Reflection;
namespace InterfaceAttributesDemo {
https://riptutorial.com/ 92
private static void GetInterfaceAttributeDemo() {
var attribute1 = (MyCustomAttribute)
typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute), true);
Console.WriteLine(attribute1 == null); // True
var attribute2 =
typeof(MyClass).GetCustomAttributes(true).OfType<MyCustomAttribute>().SingleOrDefault();
Console.WriteLine(attribute2 == null); // True
One way to retrieve interface attributes is to search for them through all the interfaces
implemented by a class.
Obsolete Attribute
System.Obsolete is an attribute that is used to mark a type or a member that has a better version,
and thus should not be used.
In case the class above is used, the compiler will give the warning "This class is obsolete. Use
SomeOtherClass instead."
https://riptutorial.com/ 93
Chapter 17: BackgroundWorker
Syntax
• bgWorker.CancellationPending //returns whether the bgWorker was cancelled during its
operation
Remarks
Performing long-running operations within the UI thread can cause your application to become
unresponsive, appearing to the user that it has stopped working. It is preferred that these tasks be
run on a background thread. Once complete, the UI can be updated.
Making changes to the UI during the BackgroundWorker's operation requires invoking the
changes to the UI thread, typically by using the Control.Invoke method on the control you are
updating. Neglecting to do so will cause your program to throw an exception.
Examples
Assigning Event Handlers to a BackgroundWorker
Once the instance of the BackgroundWorker has been declared, it must be given properties and
event handlers for the tasks it performs.
bgWorker.DoWork += bgWorker_DoWork;
https://riptutorial.com/ 94
// Work to be done here
// ...
// To get a reference to the current Backgroundworker:
BackgroundWorker worker = sender as BackgroundWorker;
// The reference to the BackgroundWorker is often used to report progress
worker.ReportProgress(...);
}
/*This is the method that will be run once the BackgroundWorker has completed its tasks */
bgWorker.RunWorkerCompleted += bgWorker_CompletedWork;
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
bgWorker.WorkerSupportsCancellation = true;
bgWorker.WorkerReportsProgress = true;
https://riptutorial.com/ 95
namespace BGWorkerExample
{
public partial class ExampleForm : Form
{
namespace BgWorkerExample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
prgProgressBar.Step = 1;
//tell the backgroundWorker to raise the "DoWork" event, thus starting it.
//Check to make sure the background worker is not already running.
if(!bgWorker.IsBusy)
bgWorker.RunWorkerAsync();
https://riptutorial.com/ 96
}
else
{
MessageBox.Show("Task Complete!");
prgProgressBar.Value = 0;
}
}
https://riptutorial.com/ 97
Chapter 18: BigInteger
Remarks
When To Use
objects are by their very nature very heavy on RAM. Consequently, they should only be
BigInteger
used when absolutely necessary, ie for numbers on a truly astronomical scale.
Further to this, all arithmetic operations on these objects are an order of magnitude slower than
their primitive counterparts, this problem gets further compounded as the number grows as they
are not of a fixed size. It is therefore feasibly possible for a rogue BigInteger to cause a crash by
consuming all of the available RAM.
Alternatives
If speed is imperative to your solution it may be more efficient to implement this functionality
yourself using a class wrapping a Byte[] and overloading the necessary operators yourself.
However, this does require a significant amount of extra effort.
Examples
Calculate the First 1,000-Digit Fibonacci Number
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);
}
}
}
https://riptutorial.com/ 98
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.
https://riptutorial.com/ 99
Chapter 19: Binary Serialization
Remarks
The binary serialization engine is part of the .NET framework, but the examples given here are
specific to C#. As compared to other serialization engines built into the .NET framework, the binary
serializer is fast and efficient and usually requires very little extra code to get it to work. However, it
is also less tolerant to code changes; that is, if you serialize an object and then make a slight
change to the object's definition, it likely will not deserialize correctly.
Examples
Making an object serializable
Add the [Serializable] attribute to mark an entire object for binary serialization:
[Serializable]
public class Vector
{
public int X;
public int Y;
public int Z;
[NonSerialized]
public decimal DontSerializeThis;
[OptionalField]
public string Name;
}
All members will be serialized unless we explicitly opt-out using the [NonSerialized] attribute. In
our example, X, Y, Z, and Name are all serialized.
All members are required to be present on deserialization unless marked with [NonSerialized] or
[OptionalField]. In our example, X, Y, and Z are all required and deserialization will fail if they are
not present in the stream. DontSerializeThis will always be set to default(decimal) (which is 0). If
Name is present in the stream, then it will be set to that value, otherwise it will be set to
default(string) (which is null). The purpose of [OptionalField] is to provide a bit of version
tolerance.
If you use the [NonSerialized] attribute, then that member will always have its default value after
deserialization (ex. 0 for an int, null for string, false for a bool, etc.), regardless of any initialization
done in the object itself (constructors, declarations, etc.). To compensate, the attributes
[OnDeserializing] (called just BEFORE deserializing) and [OnDeserialized] (called just AFTER
deserializing) together with their counterparts, [OnSerializing] and [OnSerialized] are provided.
https://riptutorial.com/ 100
Assume we want to add a "Rating" to our Vector and we want to make sure the value always
starts at 1. The way it is written below, it will be 0 after being deserialized:
[Serializable]
public class Vector
{
public int X;
public int Y;
public int Z;
[NonSerialized]
public decimal Rating = 1M;
public Vector()
{
Rating = 1M;
}
To fix this problem, we can simply add the following method inside of the class to set it to 1:
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
Rating = 1M;
}
Or, if we want to set it to a calculated value, we can wait for it to be finished deserializing and then
set it:
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
Rating = 1 + ((X+Y+Z)/3);
}
Similarly, we can control how things are written out by using [OnSerializing] and [OnSerialized].
That would get more control over serialization, how to save and load types
[Serializable]
public class Item : ISerializable
{
private string _name;
https://riptutorial.com/ 101
public string Name
{
get { return _name; }
set { _name = value; }
}
public Item ()
{
For data serialization, you can specify the desired name and the desired type
When the data is deserialized, you will be able to read the desired type
Implements a serialization surrogate selector that allows one object to perform serialization and
deserialization of another
As well allows to properly serialize or deserialize a class that is not itself serializable
https://riptutorial.com/ 102
Then you need to let your IFormatter know about the surrogates by defining and initializing a
SurrogateSelector and assigning it to your IFormatter
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace BinarySerializationExample
{
class Item
{
private string _name;
https://riptutorial.com/ 103
item.Name = (string)info.GetValue("_name", typeof(string));
return item;
}
}
class Program
{
static void Main(string[] args)
{
var item = new Item
{
Name = "Orange"
};
Serialization Binder
The binder gives you an opportunity to inspect what types are being loaded in your application
domain
https://riptutorial.com/ 104
class MyBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName.Equals("BinarySerializationExample.Item"))
return typeof(Item);
return null;
}
}
Now we can check what types are loading and on this basis to decide what we really want to
receive
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace BinarySerializationExample
{
class MyBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName.Equals("BinarySerializationExample.Item"))
return typeof(Item);
return null;
}
}
[Serializable]
public class Item
{
private string _name;
class Program
{
static void Main(string[] args)
https://riptutorial.com/ 105
{
var item = new Item
{
Name = "Orange"
};
This small example shows how you can lose backward compatibility in your programs if you do not
take care in advance about this. And ways to get more control of serialization process
Version 1
[Serializable]
class Data
{
[OptionalField]
private int _version;
And now, let us assume that in the second version of the program added a new class. And we
need to store it in an array.
https://riptutorial.com/ 106
Now code will look like this:
Version 2
[Serializable]
class NewItem
{
[OptionalField]
private string _name;
[Serializable]
class Data
{
[OptionalField]
private int _version;
[OptionalField]
private List<NewItem> _newItems;
https://riptutorial.com/ 107
And so, what would happen when you serialize the data in the program of v2 and will try to
deserialize them in the program of v1?
Why?
The ObjectManager has a different logic to resolve dependencies for arrays and for reference and
value types. We added an array of new the reference type which is absent in our assembly.
When ObjectManager attempts to resolve dependencies it builds the graph. When it sees the
array, it can not fix it immediately, so that it creates a dummy reference and then fixes the array
later.
And since this type is not in the assembly and dependencies can’t be fixed. For some reason, it
does not remove the array from the list of elements for the fixes and at the end, it throws an
exception “IncorrectNumberOfFixups”.
It is some ‘gotchas’ in the process of serialization. For some reason, it does not work correctly only
for arrays of new reference types.
A Note:
Similar code will work correctly if you do not use arrays with new classes
• Use a collection of new structures rather than classes or use a dictionary(possible classes),
because a dictionary it’s a collection of keyvaluepair(it’s structure)
• Use ISerializable, if you can't change the old code
https://riptutorial.com/ 108
Chapter 20: BindingList
Examples
Avoiding N*2 iteration
https://riptutorial.com/ 109
Chapter 21: Built-in Types
Examples
Immutable reference type - string
// single character s
char c = 's';
Value type - short, int, long (signed 16 bit, 32 bit, 64 bit integers)
// assigning a signed long to its minimum value (note the long postfix)
long l = -9223372036854775808L;
https://riptutorial.com/ 110
// 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.
Value type - ushort, uint, ulong (unsigned 16 bit, 32 bit, 64 bit integers)
// 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.
The bool keyword is an alias of System.Boolean. It is used to declare variables to store the
Boolean values, true and false.
https://riptutorial.com/ 111
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.:
This can be avoided by using the overloaded Equals method, which will give the expected result.
Alternatively, the same could be done by unboxing the left and right variables so that the int
values are compared:
Boxed value types can only be unboxed into their original Type, even if a conversion of the two Type
s is valid, e.g.:
This can be avoided by first unboxing into the original Type, e.g.:
https://riptutorial.com/ 112
Chapter 22: C# 3.0 Features
Remarks
C# version 3.0 was released as part of .Net version 3.5. Many of the features added with this
version were in support of LINQ (Language INtegrated Queries).
• LINQ
• Lambda expressions
• Extension methods
• Anonymous types
• Implicitly typed variables
• Object and Collection Initializers
• Automatically implemented properties
• Expression trees
Examples
Implicitly typed variables (var)
The var keyword allows a programmer to implicitly type a variable at compile time. var declarations
have the same type as explicitly declared variables.
The types of the above variables are int, double, StringBuilder, and an anonymous type
respectively.
It is important to note that a var variable is not dynamically typed. SquaredNumber = Builder is not
valid since you are trying to set an int to an instance of StringBuilder
//Example 1
int[] array = { 1, 5, 2, 10, 7 };
// Select squares of all odd numbers in the array sorted in descending order
IEnumerable<int> query = from x in array
https://riptutorial.com/ 113
where x % 2 == 1
orderby x descending
select x * x;
// Result: 49, 25, 1
Example 1 uses query syntax which was designed to look similar to SQL queries.
//Example 2
IEnumerable<int> query = array.Where(x => x % 2 == 1)
.OrderByDescending(x => x)
.Select(x => x * x);
// Result: 49, 25, 1 using 'array' as defined in previous example
It is important to note that, in C#, LINQ query syntax is syntactic sugar for LINQ method syntax.
The compiler translates the queries into method calls at compile time. Some queries have to be
expressed in method syntax. From MSDN - "For example, you must use a method call to express
a query that retrieves the number of elements that match a specified condition."
Lambda expresions
Lambda Expresions are an extension of anonymous methods that allow for implicitly typed
parameters and return values. Their syntax is less verbose than anonymous methods and follows
a functional programming style.
using System;
using System.Collections.Generic;
using System.Linq;
The above code will output the sum of the squares of the numbers 1 through 10 to the console.
The first lambda expression squares the numbers in the list. Since there is only 1 parameter
parenthesis may be omitted. You can include parenthesis if you wish:
https://riptutorial.com/ 114
or explicitly type the parameter but then parenthesis are required:
The lambda body is an expression and has an implicit return. You can use a statement body if you
want as well. This is useful for more complex lambdas.
The select method returns a new IEnumerable with the computed values.
The second lambda expression sums the numbers in list returned from the select method.
Parentheses are required as there are multiple parameters. The types of the parameters are
explicitly typed but this is not necessary. The below method is equivalent.
As is this one:
Anonymous types
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a
single object without having to explicitly define a type first. The type name is generated by the
compiler and is not available at the source code level. The type of each property is inferred by the
compiler.
You can make anonymous types by using the new keyword followed by a curly brace ({). Inside the
curly braces, you could define properties like on code below.
It's also possible to create an array of anonymous types. See code below:
var a = new[] {
new {
Fruit = "Apple",
Color = "Red"
},
new {
Fruit = "Banana",
Color = "Yellow"
}
};
https://riptutorial.com/ 115
select new { prod.Color, prod.Price };
https://riptutorial.com/ 116
Chapter 23: C# 4.0 Features
Examples
Optional parameters and named arguments
We can omit the argument in the call if that argument is an Optional Argument Every Optional
Argument has its own default value It will take default value if we do not supply the value A default
value of a Optional Argument must be a
1. Constant expression.
2. Must be a value type such as enum or struct.
3. Must be an expression of the form default(valueType)
public void ExampleMethod(int required, string optValue = "test", int optNum = 42)
{
//...
}
Enables you to pass the argument to the function by associating the parameter’s name No needs
for remembering the parameters position that we are not aware of always. No need to look the
order of the parameters in the parameters list of called function. We can specify parameter for
each arguments by its name.
Named arguments:
Named argument specification must appear after all fixed arguments have been specified.
If you use a named argument before a fixed argument you will get a compile time error as follows.
https://riptutorial.com/ 117
Named argument specification must appear after all fixed arguments have been specified
Variance
Generic interfaces and delegates can have their type parameters marked as covariant or
contravariant using the out and in keywords respectively. These declarations are then respected
for type conversions, both implicit and explicit, and both compile time and run time.
For example, the existing interface IEnumerable<T> has been redefined as being covariant:
The ref keyword for callers of methods is now optional when calling into methods supplied by
COM interfaces. Given a COM method with the signature
A new pseudo-type dynamic is introduced into the C# type system. It is treated as System.Object, but
in addition, any member access (method call, field, property, or indexer access, or a delegate
invocation) or application of an operator on a value of such type is permitted without any type
checking, and its resolution is postponed until run-time. This is known as duck typing or late
https://riptutorial.com/ 118
binding. For example:
In this case, dynamic type is used to avoid more verbose Reflection. It still uses Reflection under
the hood, but it's usually faster thanks to caching.
Dynamic type has applications even in mostly statically typed code, for example it makes double
dispatch posible without implementing Visitor pattern.
https://riptutorial.com/ 119
Chapter 24: C# 5.0 Features
Syntax
• Async & Await
await MyTaskAsync();
Parameters
Remarks
C# 5.0 is coupled with Visual Studio .NET 2012
Examples
Async & Await
https://riptutorial.com/ 120
asyncand await are two operators that are intended to improve performance by freeing up Threads
and waiting for operations to complete before moving forward.
Here's another example of downloading a file and handling what happens when it's progress has
changed and when the download completes (there are two ways to do this):
Method 1:
//This one using async event handlers, but not async coupled with await
private void DownloadAndUpdateAsync(string uri, string DownloadLocation){
WebClient web = new WebClient();
//Assign the event handler
web.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
web.DownloadFileCompleted += new AsyncCompletedEventHandler(FileCompleted);
//Download the file asynchronously
web.DownloadFileAsync(new Uri(uri), DownloadLocation);
}
Method 2:
https://riptutorial.com/ 121
//Assign the event handler
web.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
//Download the file async
web.DownloadFileAsync(new Uri(uri), DownloadLocation);
//Notice how there is no complete event, instead we're using techniques from the first
example
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e){
int i = 0;
i++;
doSomething();
}
private void doProcess(){
//Wait for the download to finish
await DownloadAndUpdateAsync(new Uri("http://example.com/file"))
doSomething();
}
C.I.A.s are intended as a simple way of getting attributes from whatever is calling the targeted
method. There is really only 1 way to use them and there are only 3 attributes.
Example:
//This is the "calling method": the method that is calling the target method
public void doProcess()
{
GetMessageCallerAttributes("Show my attributes.");
}
//This is the target method
//There are only 3 caller attributes
public void GetMessageCallerAttributes(string message,
//gets the name of what is calling this method
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
//gets the path of the file in which the "calling method" is in
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
//gets the line number of the "calling method"
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
//Writes lines of all the attributes
System.Diagnostics.Trace.WriteLine("Message: " + message);
System.Diagnostics.Trace.WriteLine("Member: " + memberName);
System.Diagnostics.Trace.WriteLine("Source File Path: " + sourceFilePath);
System.Diagnostics.Trace.WriteLine("Line Number: " + sourceLineNumber);
}
Example Output:
https://riptutorial.com/ 122
Chapter 25: C# 6.0 Features
Introduction
This sixth iteration of the C# language is provided by the Roslyn compiler. This compiler came out
with version 4.6 of the .NET Framework, however it can generate code in a backward compatible
manner to allow targeting earlier framework versions. C# version 6 code can be compiled in a fully
backwards compatible manner to .NET 4.0. It can also be used for earlier frameworks, however
some features that require additional framework support may not function correctly.
Remarks
The sixth version of C# was released July 2015 alongside Visual Studio 2015 and .NET 4.6.
As well as adding some new language features it includes a complete rewrite of the compiler.
Previously csc.exe was a native Win32 application written in C++, with C# 6 it is now a .NET
managed application written in C#. This rewrite was known as project "Roslyn" and the code is
now open source and available on GitHub.
Examples
Operator nameof
The nameof operator returns the name of a code element as a string. This is useful when throwing
exceptions related to method arguments and also when implementing INotifyPropertyChanged.
The nameof operator is evaluated at compile time and changes the expression into a string literal.
This is also useful for strings that are named after their member that exposes them. Consider the
following:
Since nameof expressions are compile-time constants, they can be used in attributes, case labels,
switch statements, and so on.
https://riptutorial.com/ 123
It is convenient to use nameof with Enums. Instead of:
Console.WriteLine(Enum.One.ToString());
it is possible to use:
Console.WriteLine(nameof(Enum.One))
The nameof operator can access non-static members using static-like syntax. Instead of doing:
The output will be Length in both examples. However, the latter prevents the creation of
unnecessary instances.
Although the nameof operator works with most language constructs, there are some limitations. For
example, you cannot use the nameof operator on open generic types or method return values:
Furthermore, if you apply it to a generic type, the generic type parameter will be ignored:
Console.WriteLine(nameof(List<int>)); // "List"
Console.WriteLine(nameof(List<bool>)); // "List"
6.0
https://riptutorial.com/ 124
Expression:
Usage:
Note that this approach causes an expression tree to be created on every call, so the performance
is much worse compared to nameof operator which is evaluated at compile time and has zero
overhead at runtime.
Expression-bodied function members allow the use of lambda expressions as member bodies. For
simple members, it can result in cleaner and more readable code.
Expression-bodied functions can be used for properties, indexers, methods, and operators.
Properties
public decimal TotalPrice => BasePrice + Taxes;
Is equivalent to:
View Demo
https://riptutorial.com/ 125
Indexers
public object this[string key] => dictionary[key];
Is equivalent to:
Methods
static int Multiply(int a, int b) => a * b;
Is equivalent to:
Operators
https://riptutorial.com/ 126
This also can be used by operators:
Limitations
Expression-bodied function members have some limitations. They can't contain block statements
and any other statements that contain blocks: if, switch, for, foreach, while, do, try, etc.
Some if statements can be replaced with ternary operators. Some for and foreach statements can
be converted to LINQ queries, for example:
IEnumerable<string> Digits
{
get
{
for (int i = 0; i < 10; i++)
yield return i.ToString();
}
}
In all other cases, the old syntax for function members can be used.
Expression-bodied function members can contain async/await, but it's often redundant:
Exception filters
Exception filters give developers the ability to add a condition (in the form of a boolean expression)
to a catch block, allowing the catch to execute only if the condition evaluates to true.
Exception filters allow the propagation of debug information in the original exception, where as
using an if statement inside a catch block and re-throwing the exception stops the propagation of
debug information in the original exception. With exception filters, the exception continues to
propagate upwards in the call stack unless the condition is met. As a result, exception filters make
https://riptutorial.com/ 127
the debugging experience much easier. Instead of stopping on the throw statement, the debugger
will stop on the statement throwing the exception, with the current state and all local variables
preserved. Crash dumps are affected in a similar way.
Exception filters have been supported by the CLR since the beginning and they've
been accessible from VB.NET and F# for over a decade by exposing a part of the
CLR's exception handling model. Only after the release of C# 6.0 has the functionality
also been available for C# developers.
Multiple catch blocks with when clauses may be combined. The first when clause returning true will
cause the exception to be caught. Its catch block will be entered, while the other catch clauses will
be ignored (their when clauses won't be evaluated). For example:
try
{ ... }
catch (Exception ex) when (someCondition) //If someCondition evaluates to true,
//the rest of the catches are ignored.
{ ... }
catch (NotImplementedException ex) when (someMethod()) //someMethod() will only run if
//someCondition evaluates to false
{ ... }
catch(Exception ex) // If both when clauses evaluate to false
{ ... }
It can be risky to use exception filters: when an Exception is thrown from within the when
clause, the Exception from the when clause is ignored and is treated as false. This
approach allows developers to write when clause without taking care of invalid cases.
https://riptutorial.com/ 128
public static void Main()
{
int a = 7;
int b = 0;
try
{
DoSomethingThatMightFail();
}
catch (Exception ex) when (a / b == 0)
{
// This block is never reached because a / b throws an ignored
// DivideByZeroException which is treated as false.
}
catch (Exception ex)
{
// This block is reached since the DivideByZeroException in the
// previous when clause is ignored.
}
}
View Demo
Note that exception filters avoid the confusing line number problems associated with using throw
when failing code is within the same function. For example in this case the line number is reported
as 6 instead of 3:
1. int a = 0, b = 0;
2. try {
3. int c = a / b;
4. }
5. catch (DivideByZeroException) {
6. throw;
7. }
The exception line number is reported as 6 because the error was caught and re-thrown with the
throw statement on line 6.
1. int a = 0, b = 0;
2. try {
3. int c = a / b;
4. }
5. catch (DivideByZeroException) when (a != 0) {
6. throw;
7. }
In this example a is 0 then catch clause is ignored but 3 is reported as line number. This is
because they do not unwind the stack. More specifically, the exception is not caught on line 5
because a in fact does equal 0 and thus there is no opportunity for the exception to be re-thrown
https://riptutorial.com/ 129
on line 6 because line 6 does not execute.
Be aware that while this seems to be a comfortable way of logging, it can be risky,
especially if 3rd party logging assemblies are used. These might throw exceptions
while logging in non-obvious situations that may not be detected easily (see Risky
when(...) clause above).
try
{
DoSomethingThatMightFail(s);
}
catch (Exception ex) when (Log(ex, "An error occurred"))
{
// This catch block will never be reached
}
// ...
View Demo
The common approach in previous versions of C# was to log and re-throw the exception.
6.0
try
{
DoSomethingThatMightFail(s);
}
catch (Exception ex)
{
Log(ex, "An error occurred");
throw;
}
// ...
https://riptutorial.com/ 130
View Demo
Produced Output:
Start
https://riptutorial.com/ 131
EvaluatesTo: True
Inner Finally
Catch
Outer Finally
View Demo
In the example above, if the method SomeOperation does not wish to "leak" the global state changes
to caller's when clauses, it should also contain a catch block to modify the state. For example:
It is also common to see IDisposable helper classes leveraging the semantics of using blocks to
achieve the same goal, as IDisposable.Dispose will always be called before an exception called
within a using block starts bubbling up the stack.
Auto-property initializers
Introduction
Properties can be initialized with the = operator after the closing }. The Coordinate class below
shows the available options for initializing a property:
6.0
https://riptutorial.com/ 132
You can initialize auto-properties that have different visibility on their accessors. Here’s an
example with a protected setter:
Read-Only Properties
In addition to flexibility with visibility, you can also initialize read-only auto-properties. Here’s an
example:
This example also shows how to initialize a property with a complex type. Also, auto-properties
can’t be write-only, so that also precludes write-only initialization.
6.0
public Coordinate()
{
_z = 42;
}
}
Note: Before C# 6.0, you could still initialize read and write auto implemented properties
(properties with a getter and a setter) from within the constructor, but you could not initialize the
property inline with its declaration
View Demo
https://riptutorial.com/ 133
Usage
Initializers must evaluate to static expressions, just like field initializers. If you need to reference
non-static members, you can either initialize properties in constructors like before, or use
expression-bodied properties. Non-static expressions, like the one below (commented out), will
generate a compiler error:
This method can also be applied to properties with different level of accessors:
The auto-property initializer allows assignment of properties directly within their declaration. For
read-only properties, it takes care of all the requirements required to ensure the property is
immutable. Consider, for example, the FingerPrint class in the following example:
View Demo
Cautionary notes
https://riptutorial.com/ 134
Take care to not confuse auto-property or field initializers with similar-looking expression-body
methods which make use of => as opposed to =, and fields which do not include { get; }.
Missing { get; } in the property declaration results in a public field. Both read-only auto-property
Users1 and read-write field Users2 are initialized only once, but a public field allows changing
collection instance from outside the class, which is usually undesirable. Changing a read-only
auto-property with expression body to read-only property with initializer requires not only removing
> from =>, but adding { get; }.
The different symbol (=> instead of =) in Users3 results in each access to the property returning a
new instance of the HashSet<UserDto> which, while valid C# (from the compiler's point of view) is
unlikely to be the desired behavior when used for a collection member.
Index initializers
Index initializers make it possible to create and initialize objects with indexes at the same time.
https://riptutorial.com/ 135
["foo"] = 34,
["bar"] = 42
};
Any object that has an indexed getter or setter can be used with this syntax:
class Program
{
public class MyClassWithIndexer
{
public int this[string index]
{
set
{
Console.WriteLine($"Index: {index}, value: {value}");
}
}
}
Console.ReadKey();
}
}
Output:
View Demo
If the class has multiple indexers it is possible to assign them all in a single group of statements:
class Program
{
public class MyClassWithIndexer
{
public int this[string index]
{
set
{
Console.WriteLine($"Index: {index}, value: {value}");
}
}
public string this[int index]
{
set
{
Console.WriteLine($"Index: {index}, value: {value}");
}
https://riptutorial.com/ 136
}
}
Output:
It should be noted that the indexer set accessor might behave differently compared to an Add
method (used in collection initializers).
For example:
versus:
String interpolation
String interpolation allows the developer to combine variables and text to form a string.
Basic Example
Two int variables are created: foo and bar.
https://riptutorial.com/ 137
int bar = 42;
Console.WriteLine(resultString);
Output:
View Demo
Output:
View Demo
https://riptutorial.com/ 138
Expressions
With string interpolation, expressions within curly braces {} can also be evaluated. The result will
be inserted at the corresponding location within the string. For example, to calculate the maximum
of foo and bar and insert it, use Math.Max within the curly braces:
Output:
Note: Any leading or trailing whitespace (including space, tab and CRLF/newline) between the
curly brace and the expression is completely ignored and not included in the output
View Demo
Output:
View Demo
Output:
View Demo
Statements with a Conditional (Ternary) Operator can also be evaluated within the interpolation.
However, these must be wrapped in parentheses, since the colon is otherwise used to indicate
formatting as shown above:
Console.WriteLine($"{(foo > bar ? "Foo is larger than bar!" : "Bar is larger than foo!")}");
Output:
View Demo
https://riptutorial.com/ 139
Conditional expressions and format specifiers can be mixed:
Output:
Escape sequences
Escaping backslash (\) and quote (") characters works exactly the same in interpolated strings as
in non-interpolated strings, for both verbatim and non-verbatim string literals:
Console.WriteLine($"Foo is: {foo}. In a non-verbatim string, we need to escape \" and \\ with
backslashes.");
Console.WriteLine($@"Foo is: {foo}. In a verbatim string, we need to escape "" with an extra
quote, but we don't need to escape \");
Output:
Foo is 34. In a non-verbatim string, we need to escape " and \ with backslashes.
Foo is 34. In a verbatim string, we need to escape " with an extra quote, but we don't
need to escape \
To include a curly brace { or } in an interpolated string, use two curly braces {{ or }}:
Output:
{foo} is: 34
View Demo
FormattableString type
The type of a $"..." string interpolation expression is not always a simple string. The compiler
decides which type to assign depending on the context:
This is also the order of type preference when the compiler needs to choose which overloaded
method is going to be called.
https://riptutorial.com/ 140
A new type, System.FormattableString, represents a composite format string, along with the
arguments to be formatted. Use this to write applications that handle the interpolation arguments
specifically:
// ...
}
For example, one could choose not to incur the performance cost of formatting the string if the
logging level was already going to filter out the log item.
Implicit conversions
There are implicit type conversions from an interpolated string:
You can also produce an IFormattable variable that allows you to convert the string with invariant
context:
https://riptutorial.com/ 141
}
public static string Invariant(FormattableString formattableString)
{
return formattableString?.ToString(CultureInfo.InvariantCulture);
}
}
Then, to produce a correct string for the current culture, just use the expression:
Note: Current and Invariant cannot be created as extension methods because, by default, the
compiler assigns type String to interpolated string expression which causes the following code to
fail to compile:
FormattableString class already contains Invariant() method, so the simplest way of switching to
invariant culture is by relying on using static:
https://riptutorial.com/ 142
var fooBar = (from DataRow x in fooBarTable.Rows
select string.Format("{0}{1}", x["foo"], x["bar"])).ToList();
// ...
Logger.Log(string.Format(ErrorFormat, ex));
Interpolated strings, however, will not compile with placeholders referring to non-existent variables.
The following will not compile:
// ...
Logger.Log(FormatError(ex));
String interpolation process occurs at compile time, unlike formatting string with string.Format
https://riptutorial.com/ 143
which occurs at runtime. Expressions in an interpolated string must reference names in the current
context and need to be stored in resource files. That means that if you want to use localization you
have to do it like:
If the resource strings for the languages used above are correctly stored in the individual resource
files, you should get the following output:
Note that this implies that the name follows the localized string in every language. If that is not the
case, you need to add placeholders to the resource strings and modify the function above or you
need to query the culture info in the function and provide a switch case statement containing the
different cases. For more details about resource files, see How to use localization in C#.
It is a good practice to use a default fallback language most people will understand, in case a
translation is not available. I suggest to use English as default fallback language.
Recursive interpolation
Although not very useful, it is allowed to use an interpolated string recursively inside another's
curly brackets:
https://riptutorial.com/ 144
Console.WriteLine($"String has {$"My class is called {nameof(MyClass)}.".Length} chars:");
Console.WriteLine($"My class is called {nameof(MyClass)}.");
Output:
It is possible to use await expression to apply await operator to Tasks or Task(OfTResult) in the
catch and finally blocks in C#6.
It was not possible to use the await expression in the catch and finally blocks in earlier versions
due to compiler limitations. C#6 makes awaiting async tasks a lot easier by allowing the await
expression.
try
{
//since C#5
await service.InitializeAsync();
}
catch (Exception e)
{
//since C#6
await logger.LogAsync(e);
}
finally
{
//since C#6
await service.CloseAsync();
}
It was required in C# 5 to use a bool or declare an Exception outside the try catch to perform async
operations. This method is shown in the following example:
try
{
// Since C#5
await service.InitializeAsync();
}
catch (Exception e)
{
// Declare bool or place exception inside variable
error = true;
ex = e;
}
https://riptutorial.com/ 145
// Handle async task
}
Null propagation
The ?. operator and ?[...] operator are called the null-conditional operator. It is also sometimes
referred to by other names such as the safe navigation operator.
This is useful, because if the . (member accessor) operator is applied to an expression that
evaluates to null, the program will throw a NullReferenceException. If the developer instead uses
the ?. (null-conditional) operator, the expression will evaluate to null instead of throwing an
exception.
Note that if the ?. operator is used and the expression is non-null, ?. and . are equivalent.
Basics
var teacherName = classroom.GetTeacher().Name;
// throws NullReferenceException if GetTeacher() returns null
View Demo
If the classroom does not have a teacher, GetTeacher() may return null. When it is null and the Name
property is accessed, a NullReferenceException will be thrown.
If we modify this statement to use the ?. syntax, the result of the entire expression will be null:
View Demo
Subsequently, if classroom could also be null, we could also write this statement as:
View Demo
This is an example of short-circuiting: When any conditional access operation using the null-
https://riptutorial.com/ 146
conditional operator evaluates to null, the entire expression evaluates to null immediately, without
processing the rest of the chain.
When the terminal member of an expression containing the null-conditional operator is of a value
type, the expression evaluates to a Nullable<T> of that type and so cannot be used as a direct
replacement for the expression without ?..
https://riptutorial.com/ 147
will not evaluate to null. It will just prevent a NullReferenceException.
When invoking an event, traditionally, it is best practice to check if the event is null in case no
subscribers are present:
Since the null-conditional operator has been introduced, the invocation can be reduced to a single
line:
OnCompleted?.Invoke(EventArgs.Empty);
Limitations
Null-conditional operator produces rvalue, not lvalue, that is, it cannot be used for property
assignment, event subscription etc. For example, the following code will not work:
Gotchas
Note that:
https://riptutorial.com/ 148
int? nameLength = (person?.Name).Length; // avoid this
Despite ternary operator ?: is used here for explaining the difference between two cases, these
operators are not equivalent. This can be easily demonstrated with the following example:
void Main()
{
var foo = new Foo();
Console.WriteLine("Null propagation");
Console.WriteLine(foo.Bar?.Length);
Console.WriteLine("Ternary");
Console.WriteLine(foo.Bar != null ? foo.Bar.Length : (int?)null);
}
class Foo
{
public string Bar
{
get
{
Console.WriteLine("I was read");
return string.Empty;
}
}
}
Which outputs:
Null propagation
I was read
0
Ternary
I was read
I was read
0
View Demo
https://riptutorial.com/ 149
And this difference somewhat explains why null propagation operator is not yet supported in
expression trees.
The using static [Namespace.Type] directive allows the importing of static members of types and
enumeration values. Extension methods are imported as extension methods (from just one type),
not into top-level scope.
6.0
class Program
{
static void Main()
{
BackgroundColor = DarkBlue;
WriteLine(Sqrt(2));
}
}
6.0
using System;
class Program
{
static void Main()
{
Console.BackgroundColor = ConsoleColor.DarkBlue;
Console.WriteLine(Math.Sqrt(2));
}
}
Following snippet shows an example of passing a method group (as opposed to a lambda) when a
delegate is expected. Overload resolution will now resolve this instead of raising an ambiguous
overload error due to the ability of C# 6 to check the return type of the method that was passed.
using System;
public class Program
{
public static void Main()
{
Overloaded(DoSomething);
}
https://riptutorial.com/ 150
{
Console.WriteLine("overload with action called");
}
Results:
6.0
Output
View Demo
5.0
Error
error CS0121: The call is ambiguous between the following methods or properties:
'Program.Overloaded(System.Action)' and 'Program.Overloaded(System.Func)'
C# 6 can also handle well the following case of exact matching for lambda expressions which
would have resulted in an error in C# 5.
using System;
class Program
{
static void Foo(Func<Func<long>> func) {}
static void Foo(Func<Func<int>> func) {}
Parentheses are now forbidden around named parameters. The following compiles in C#5, but not
C#6
5.0
https://riptutorial.com/ 151
Console.WriteLine((value: 23));
Operands of is and as are no longer allowed to be method groups. The following compiles in C#5,
but not C#6
5.0
The native compiler allowed this (although it did show a warning), and in fact didn’t
even check extension method compatibility, allowing crazy things like 1.Any is string
or IDisposable.Dispose is object.
Collection initialization syntax can be used when instantiating any class which implements
IEnumerable and has a method named Add which takes a single parameter.
In previous versions, this Add method had to be an instance method on the class being initialized.
In C#6, it can also be an extension method.
https://riptutorial.com/ 152
{
var collection1 = new CollectionWithAdd{1,2,3}; // Valid in all C# versions
var collection2 = new CollectionWithoutAdd{4,5,6}; // Valid only since C# 6
}
}
In C# 5.0 and earlier the developer could only suppress warnings by number. With the introduction
of Roslyn Analyzers, C# needs a way to disable warnings issued from specific libraries. With C#
6.0 the pragma directive can suppress warnings by name.
Before:
C# 6.0:
https://riptutorial.com/ 153
Chapter 26: C# 7.0 Features
Introduction
C# 7.0 is the seventh version of C#. This version contains some new features: language support
for Tuples, local functions, out var declarations, digit separators, binary literals, pattern matching,
throw expressions, ref return and ref local and extended expression bodied members list.
Examples
out var declaration
A common pattern in C# is using bool TryParse(object input, out object value) to safely parse
objects.
The out var declaration is a simple feature to improve readability. It allows a variable to be
declared at the same time that is it passed as an out parameter.
A variable declared this way is scoped to the remainder of the body at the point in which it is
declared.
Example
Using TryParse prior to C# 7.0, you must declare a variable to receive the value before calling the
function:
7.0
int value;
if (int.TryParse(input, out value))
{
Foo(value); // ok
}
else
{
Foo(value); // value is zero
}
Foo(value); // ok
In C# 7.0, you can inline the declaration of the variable passed to the out parameter, eliminating
the need for a separate variable declaration:
7.0
https://riptutorial.com/ 154
if (int.TryParse(input, out var value))
{
Foo(value); // ok
}
else
{
Foo(value); // value is zero
}
Foo(value); // still ok, the value in scope within the remainder of the body
If some of the parameters that a function returns in out is not needed you can use the discard
operator _.
An out var declaration can be used with any existing function which already has out parameters.
The function declaration syntax remains the same, and no additional requirements are needed to
make the function compatible with an out var declaration. This feature is simply syntactic sugar.
Another feature of out var declaration is that it can be used with anonymous types.
7.0
var a = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var groupedByMod2 = a.Select(x => new
{
Source = x,
Mod2 = x % 2
})
.GroupBy(x => x.Mod2)
.ToDictionary(g => g.Key, g => g.ToArray());
if (groupedByMod2.TryGetValue(1, out var oddElements))
{
Console.WriteLine(oddElements.Length);
}
In this code we create a Dictionary with int key and array of anonymous type value. In the
previous version of C# it was impossible to use TryGetValue method here since it required you to
declare the out variable (which is of anonymous type!). However, with out var we do not need to
explicitly specify the type of the out variable.
Limitations
Note that out var declarations are of limited use in LINQ queries as expressions are interpreted as
expression lambda bodies, so the scope of the introduced variables is limited to these lambdas.
For example, the following code will not work:
var nums =
from item in seq
let success = int.TryParse(item, out var tmp)
https://riptutorial.com/ 155
select success ? tmp : 0; // Error: The name 'tmp' does not exist in the current context
References
• Original out var declaration proposal on GitHub
Binary literals
Binary literals allow constructing numbers from zeroes and ones, which makes seeing which bits
are set in the binary representation of a number much easier. This can be useful for working with
binary flags.
The following are equivalent ways of specifying an int with value 34 (=25 + 21):
// Existing methods:
int a2 = 0x22; // hexadecimal: every digit corresponds to 4 bits
int a3 = 34; // decimal: hard to visualise which bits are set
int a4 = (1 << 5) | (1 << 1); // bitwise arithmetic: combining non-zero bits
Flags enumerations
Before, specifying flag values for an enum could only be done using one of the three methods in this
example:
[Flags]
public enum DaysOfWeek
{
// Previously available methods:
// decimal hex bit shifting
Monday = 1, // = 0x01 = 1 << 0
Tuesday = 2, // = 0x02 = 1 << 1
Wednesday = 4, // = 0x04 = 1 << 2
Thursday = 8, // = 0x08 = 1 << 3
Friday = 16, // = 0x10 = 1 << 4
Saturday = 32, // = 0x20 = 1 << 5
Sunday = 64, // = 0x40 = 1 << 6
With binary literals it is more obvious which bits are set, and using them does not require
understanding hexadecimal numbers and bitwise arithmetic:
https://riptutorial.com/ 156
[Flags]
public enum DaysOfWeek
{
Monday = 0b00000001,
Tuesday = 0b00000010,
Wednesday = 0b00000100,
Thursday = 0b00001000,
Friday = 0b00010000,
Saturday = 0b00100000,
Sunday = 0b01000000,
Digit separators
The underscore _ may be used as a digit separator. Being able to group digits in large numeric
literals has a significant impact on readability.
The underscore may occur anywhere in a numeric literal except as noted below. Different
groupings may make sense in different scenarios or with different numeric bases.
Any sequence of digits may be separated by one or more underscores. The _ is allowed in
decimals as well as exponents. The separators have no semantic impact - they are simply
ignored.
Basics
A tuple is an ordered, finite list of elements. Tuples are commonly used in programming as a
means to work with one single entity collectively instead of individually working with each of the
tuple's elements, and to represent individual rows (ie. "records") in a relational database.
https://riptutorial.com/ 157
In C# 7.0, methods can have multiple return values. Behind the scenes, the compiler will use the
new ValueTuple struct.
Side note: for this to work in Visual Studio 2017, you need to get the System.ValueTuple package.
If a tuple-returning method result is assigned to a single variable you can access the members by
their defined names on the method signature:
Tuple Deconstruction
Tuple deconstruction separates a tuple into its parts.
For example, invoking GetTallies and assigning the return value to two separate variables
deconstructs the tuple into those two variables:
You can also use shorter syntax, with var outside of ():
int s, c;
(s, c) = GetTallies();
Interestingly, any object can be deconstructed by defining a Deconstruct method in the class:
https://riptutorial.com/ 158
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
In this case, the (localFirstName, localLastName) = person syntax is invoking Deconstruct on the
person.
Deconstruction can even be defined in an extension method. This is equivalent to the above:
An alternative approach for the Person class is to define the Name itself as a Tuple. Consider the
following:
class Person
{
public (string First, string Last) Name { get; }
Then you can instantiate a person like so (where we can take a tuple as an argument):
Tuple Initialization
https://riptutorial.com/ 159
You can also arbitrarily create tuples in code:
Console.WriteLine(name.Item2);
// Outputs Smith
When creating a tuple, you can assign ad-hoc item names to the members of the tuple:
Type inference
Multiple tuples defined with the same signature (matching types and count) will be inferred as
matching types. For example:
stats can be returned since the declaration of the stats variable and the method's return signature
are a match.
While the ValueTuple class itself does not preserve information for member names the information
is available through reflection in a TupleElementNamesAttribute. This attribute is not applied to the
tuple itself but to method parameters, return values, properties and fields. This allows tuple item
names to be preserved across assemblies i.e. if a method returns (string name, int count) the
names name and count will be available to callers of the method in another assembly because the
return value will be marked with TupleElementNameAttribute containing the values "name" and
"count".
https://riptutorial.com/ 160
Use with generics and async
The new tuple features (using the underlying ValueTuple type) fully support generics and can be
used as generic type parameter. That makes it possible to use them with the async/await pattern:
Example:
if (result == null)
throw new ArgumentException("combo not found");
return result.Item3;
}
https://riptutorial.com/ 161
var result = labels
.Where(w => w.firstThingy == firstElement && w.secondThingyLabel == secondElement)
.FirstOrDefault();
if (result == null)
throw new ArgumentException("combo not found");
return result.foundValue;
}
Though the naming on the example tuple above is pretty generic, the idea of relevant labels allows
for a deeper understanding of what is being attempted in the code over referencing "item1",
"item2", and "item3".
References
• Original Tuples language feature proposal on GitHub
• A runnable VS 15 solution for C# 7.0 features
• NuGet Tuple Package
Local functions
Local functions are defined within a method and aren't available outside of it. They have access to
all local variables and support iterators, async/await and lambda syntax. This way, repetitions
specific to a function can be functionalized without crowding the class. As a side effect, this
improves intellisense suggestion performance.
Example
double GetCylinderVolume(double radius, double height)
{
return getVolume();
double getVolume()
https://riptutorial.com/ 162
{
// You can declare inner-local functions in a local function
double GetCircleArea(double r) => Math.PI * r * r;
// ALL parents' variables are accessible even though parent doesn't have any input.
return GetCircleArea(radius) * height;
}
}
Local functions considerably simplify code for LINQ operators, where you usually have to separate
argument checks from actual logic to make argument checks instant, not delayed until after
iteration started.
Example
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
return iterator();
IEnumerable<TSource> iterator()
{
foreach (TSource element in source)
if (predicate(element))
yield return element;
}
}
Example
async Task WriteEmailsAsync()
{
var emailRegex = new Regex(@"(?i)[a-z0-9_.+-]+@[a-z0-9-]+\.[a-z0-9-.]+");
IEnumerable<string> emails1 = await getEmailsFromFileAsync("input1.txt");
IEnumerable<string> emails2 = await getEmailsFromFileAsync("input2.txt");
await writeLinesToFileAsync(emails1.Concat(emails2), "output.txt");
https://riptutorial.com/ 163
}
One important thing that you may have noticed is that local functions can be defined under the
return statement, they do not need to be defined above it. Additionally, local functions typically
follow the "lowerCamelCase" naming convention as to more easily differentiate themselves from
class scope functions.
Pattern Matching
Pattern matching extensions for C# enable many of the benefits of pattern matching from
functional languages, but in a way that smoothly integrates with the feel of the underlying
language
switch expression
Pattern matching extends the switch statement to switch on types:
class Geometry {}
switch (g)
{
https://riptutorial.com/ 164
case Triangle t:
Console.WriteLine($"{t.Width} {t.Height} {t.Base}");
break;
case Rectangle sq when sq.Width == sq.Height:
Console.WriteLine($"Square rectangle: {sq.Width} {sq.Height}");
break;
case Rectangle r:
Console.WriteLine($"{r.Width} {r.Height}");
break;
case Square s:
Console.WriteLine($"{s.Width}");
break;
default:
Console.WriteLine("<other>");
break;
}
}
is expression
Pattern matching extends the is operator to check for a type and declare a new variable at the
same time.
Example
7.0
string s = o as string;
if(s != null)
{
// do something with s
}
7.0
if(o is string s)
{
//Do something with s
};
Also note that the scope of the pattern variable s is extended to outside the if block reaching the
end of the enclosing scope, example:
if(someCondition)
{
if(o is string s)
{
//Do something with s
}
else
{
https://riptutorial.com/ 165
// s is unassigned here, but accessible
}
Ref returns and ref locals are useful for manipulating and returning references to blocks of
memory instead of copying memory without resorting to unsafe pointers.
Ref Return
public static ref TValue Choose<TValue>(
Func<bool> condition, ref TValue left, ref TValue right)
{
return condition() ? ref left : ref right;
}
With this you can pass two values by reference with one of them being returned based on some
condition:
Ref Local
public static ref int Max(ref int first, ref int second, ref int third)
{
ref int max = first > second ? ref first : ref second;
return max > third ? ref max : ref third;
}
…
int a = 1, b = 2, c = 3;
Max(ref a, ref b, ref c) = 4;
Debug.Assert(a == 1); // true
Debug.Assert(b == 2); // true
Debug.Assert(c == 4); // true
https://riptutorial.com/ 166
byte[] b = new byte[4] { 0x42, 0x42, 0x42, 0x42 };
0x0EF00EF0;
Assert.Equal(0xFE, b[0] | b[1] | b[2] | b[3]);
Beware of endianness when doing this, though, e.g. check BitConverter.IsLittleEndian if needed
and handle accordingly.
Additionally, one can check if two ref values are the same i.e. same address:
Links
Roslyn Github Issue
System.Runtime.CompilerServices.Unsafe on github
throw expressions
https://riptutorial.com/ 167
C# 7.0 allows throwing as an expression in certain places:
class Person
{
public string Name { get; }
Prior to C# 7.0, if you wanted to throw an exception from an expression body you would have to:
if (spoonsArray == null)
{
throw new Exception("There are no spoons");
}
Or
var spoonsArray = spoons.Length > 0 ? spoons : throw new Exception("There are no spoons");
C# 7.0 adds accessors, constructors and finalizers to the list of things that can have expression
bodies:
class Person
{
private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int,
string>();
https://riptutorial.com/ 168
public Person(string name) => names.TryAdd(id, name); // constructors
Also see the out var declaration section for the discard operator.
ValueTask
is a class and causes the unnecessary overhead of its allocation when the result is
Task<T>
immediately available.
ValueTask<T>is a structure and has been introduced to prevent the allocation of a Task object in
case the result of the async operation is already available at the time of awaiting.
1. Performance increase
Here's a Task<T> example:
• No heap allocation if the result is known synchronously (which it is not in this case because
of the Task.Delay, but often is in many real-world async/await scenarios)
• Takes 65ns with JIT
https://riptutorial.com/ 169
2. Increased implementation flexibility
Implementations of an async interface wishing to be synchronous would otherwise be forced to
use either Task.Run or Task.FromResult (resulting in the performance penalty discussed above).
Thus there's some pressure against synchronous implementations.
But with ValueTask<T>, implementations are more free to choose between being synchronous or
asynchronous without impacting callers.
interface IFoo<T>
{
ValueTask<T> BarAsync();
}
With ValueTask, the above code will work with either synchronous or asynchronous
implementations:
Synchronous implementation:
Asynchronous implementation
https://riptutorial.com/ 170
Notes
Although ValueTask struct was being planned to be added to C# 7.0, it has been kept as another
library for the time being. ValueTask<T> System.Threading.Tasks.Extensions package can be
downloaded from Nuget Gallery
https://riptutorial.com/ 171
Chapter 27: C# Authentication handler
Examples
Authentication handler
/// <summary>
/// Default overridden method which performs authentication.
/// </summary>
/// <param name="request">Http request message.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Returns http response message of type <see cref="HttpResponseMessage"/>
class asynchronously.</returns>
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Headers.Contains(securityToken))
{
bool authorized = Authorize(request);
if (!authorized)
{
return ApiHttpUtility.FromResult(request, false,
HttpStatusCode.Unauthorized, MessageTypes.Error, Resource.UnAuthenticatedUser);
}
}
else
{
return ApiHttpUtility.FromResult(request, false, HttpStatusCode.BadRequest,
MessageTypes.Error, Resource.UnAuthenticatedUser);
}
/// <summary>
/// Authorize user by validating token.
/// </summary>
/// <param name="requestMessage">Authorization context.</param>
/// <returns>Returns a value indicating whether current request is authenticated or
not.</returns>
private bool Authorize(HttpRequestMessage requestMessage)
{
try
{
HttpRequest request = HttpContext.Current.Request;
string token = request.Headers[securityToken];
return SecurityUtility.IsTokenValid(token, request.UserAgent,
HttpContext.Current.Server.MapPath("~/Content/"), requestMessage);
}
catch (Exception)
https://riptutorial.com/ 172
{
return false;
}
}
}
https://riptutorial.com/ 173
Chapter 28: C# Script
Examples
Simple code evaluation
https://riptutorial.com/ 174
Chapter 29: Caching
Examples
MemoryCache
https://riptutorial.com/ 175
Chapter 30: Casting
Remarks
Casting is not the same as Converting. It is possible to convert the string value "-1" to an integer
value (-1), but this must be done through library methods like Convert.ToInt32() or Int32.Parse(). It
cannot be done using casting syntax directly.
Examples
Cast an object to a base type
string IMyInterface2.GetName()
{
return "IMyInterface2";
}
}
// Outputs :
// I am : IMyInterface1
// I am : IMyInterface2
https://riptutorial.com/ 176
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.
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
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.
Note that null values have no type, so the as keyword will safely yield null when casting any null
value.
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.
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);
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.
https://riptutorial.com/ 177
if(value is int)
{
Console.WriteLine(value + "is an int");
}
Explicit casting operators can be used to perform conversions of numeric types, even though they
don't extend or implement one another.
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.
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 expression:
https://riptutorial.com/ 178
But we can add some explicit conversion operators to JsExpression, to allow a simple conversion
when using explicit casting.
// 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.
// Usage:
JsExpression intExpression = -1;
Console.WriteLine(intExpression.IsEqualTo(-1.0)); // (-1 == -1.0)
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.
When things2 is evaluated, the Cast<>() method will try to cast all of the values in things into Thing
s. 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
https://riptutorial.com/ 179
numeric conversions.
https://riptutorial.com/ 180
Chapter 31: Checked and Unchecked
Syntax
• checked(a + b) // checked expression
• unchecked(a + b) // unchecked expression
• checked { c = a + b; c += 5; } // checked block
• unchecked { c = a + b; c += 5; } // unchecked block
Examples
Checked and Unchecked
short m = 32767;
short n = 32767;
int result1 = checked((short)(m + n)); //will throw an OverflowException
int result2 = unchecked((short)(m + n)); // will return -2
If neither of these are specified then the default context will rely on other factors, such as compiler
options.
The keywords can also create scopes in order to (un)check multiple operations.
short m = 32767;
short n = 32767;
checked
{
int result1 = (short)(m + n); //will throw an OverflowException
}
unchecked
{
int result2 = (short)(m + n); // will return -2
}
https://riptutorial.com/ 181
Chapter 32: CLSCompliantAttribute
Syntax
1. [assembly:CLSCompliant(true)]
2. [CLSCompliant(true)]
Parameters
Constructor Parameter
Remarks
The Common Language Specification (CLS) is a set of base rules to which any language targeting
the CLI(language which confirms the Common Language Infrastructure specifications) should
confirm in order to interoperate with other CLS-compliant languages.
You should mark your assembly as CLSCompliant in most cases when you are distributing
libraries. This attribute will guarantee you that your code will be usable by all CLS-compliant
languages. This means that your code can be consumed by any language that can be compiled
and run on CLR(Common Language Runtime)
When your assembly is marked with CLSCompliantAttribute, the compiler will check if your code
violates any of CLS rules and return warning if it is needed.
Examples
Access Modifier to which CLS rules apply
using System;
[assembly:CLSCompliant(true)]
namespace CLSDoc
{
https://riptutorial.com/ 182
//Warning CS3003 Type of 'Cat.DaysTillVacination' is not CLS-compliant
protected UInt16 DaysTillVacination
{
get { return _daysTillVacination; }
}
return increasedAge;
}
}
}
using System;
[assembly:CLSCompliant(true)]
namespace CLSDoc
{
https://riptutorial.com/ 183
return ptr;
}
}
}
using System;
[assembly:CLSCompliant(true)]
namespace CLSDoc
{
}
}
using System;
[assembly:CLSCompliant(true)]
namespace CLSDoc
{
https://riptutorial.com/ 184
Violation of CLS rule: Inherit from non CLSComplaint class
using System;
[assembly:CLSCompliant(true)]
namespace CLSDoc
{
[CLSCompliant(false)]
public class Animal
{
public int age = 0;
}
https://riptutorial.com/ 185
Chapter 33: Code Contracts
Syntax
1. Contract.Requires(Condition,userMessage)
Contract.Requires(Condition,userMessage)
Contract.Result<T>
Contract.Ensures()
Contract.Invariants()
Remarks
.NET supports the Design by Contract idea via its Contracts class found in the System.Diagnostics
namespace and introduced in .NET 4.0. Code Contracts API includes classes for static and
runtime checks of code and allows you to define preconditions, postconditions, and invariants
within a method. The preconditions specify the conditions the parameters must fulfill before a
method can execute, postconditions that are verified upon completion of a method, and the
invariants define the conditions that do not change during the execution of a method.
Tracking issues of an application when your application is running, is one the foremost concerns of
all the developers and administrators. Tracking can be performed in many ways. For example -
• You can apply tracing on our application and get the details of an application when the
application is running
• You can use event logging mechanism when you are running the application. The messages
can be seen using Event Viewer
• You can apply Performance Monitoring after a specific time interval and write live data from
your application.
Code Contracts uses a different approach for tracking and managing issues within an application.
Instead of validating everything that is returned from a method call, Code Contracts with the help
of preconditions, postconditions, and invariants on methods, ensure that everything entering and
leaving your methods are correct.
Examples
Preconditions
https://riptutorial.com/ 186
namespace CodeContractsDemo
{
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
this._payments.Add(payment);
}
}
}
Postconditions
return total;
}
Invariants
namespace CodeContractsDemo
{
using System;
using System.Diagnostics.Contracts;
public Point()
{
}
https://riptutorial.com/ 187
this.X = x;
this.Y = y;
}
[ContractInvariantMethod]
private void ValidateCoordinates()
{
Contract.Invariant(this.X >= 0);
Contract.Invariant(this.Y >= 0);
}
}
}
[ContractClass(typeof(ValidationContract))]
interface IValidation
{
string CustomerID{get;set;}
string Password{get;set;}
}
[ContractClassFor(typeof(IValidation))]
sealed class ValidationContract:IValidation
{
string IValidation.CustomerID
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Customer
ID cannot be null!!");
}
https://riptutorial.com/ 188
}
string IValidation.Password
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Password
cannot be null!!");
}
}
}
class Validation:IValidation
{
public string GetCustomerPassword(string customerID)
{
Contract.Requires(!string.IsNullOrEmpty(customerID),"Customer ID cannot be Null");
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(customerID),
"Exception!!");
Contract.Ensures(Contract.Result<string>() != null);
string password="AAA@1234";
if (customerID!=null)
{
return password;
}
else
{
return null;
}
https://riptutorial.com/ 189
}
}
In the above code, we have defined an interface called IValidation with an attribute
[ContractClass]. This attribute takes an address of a class where we have implemented a contract
for an Interface. The class ValidationContract makes use of properties defined in the interface and
checks for the null values using Contract.Requires<T>. T is an exception class.
We have also marked the get accessor with an attribute [Pure]. The pure attribute ensures that the
method or a property does not change the instance state of a class in which IValidation interface
is implemented.
https://riptutorial.com/ 190
Chapter 34: Code Contracts and Assertions
Examples
Assertions to check logic should always be true
Assertions are used not to perform testing of input parameters, but to verify that program flow is
corect -- i.e., that you can make certain assumptions about your code at a certain point in time. In
other words: a test done with Debug.Assert should always assume that the value tested is true.
Debug.Assert only executes in DEBUG builds; it is filtered out of RELEASE builds. It must be
considered a debugging tool in addition to unit testing and not as a replacement of code contracts
or input validation methods.
Here assert is a good choice because we can assume that RetrieveSystemConfiguration() will
return a valid value and will never return null.
First, we may assume that RetrieveUserData() will return a valid value. Then, before using the Age
property, we verify the assumption (which should always be true) that the age of the user is strictly
positive.
Assert is not for input validation because it is incorrect to assume that this assertion will always be
true. You must use input validation methods for that. In the case above, you should also verify that
the input value is a number in the first place.
https://riptutorial.com/ 191
Chapter 35: Collection Initializers
Remarks
The only requirement for an object to be initialized using this syntactic sugar is that the type
implements System.Collections.IEnumerable and the Add method. Although we call it a collection
initializer, the object does not have to be an collection.
Examples
Collection initializers
Collection initializers are syntactic sugar for Add() calls. Above code is equivalent to:
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:
C# 6 Index Initializers
Starting with C# 6, collections with indexers can be initialized by specifying the index to assign in
https://riptutorial.com/ 192
square brackets, followed by an equals sign, followed by the value to assign.
Dictionary Initialization
An example of this syntax using a Dictionary:
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.
https://riptutorial.com/ 193
This would output:
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 },
"baz",
123.45d,
};
}
}
https://riptutorial.com/ 194
public class LotteryTicket : IEnumerable{
public int[] LuckyNumbers;
public string UserName;
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:
The collection property can be readonly and still support collection initializer syntax. Consider this
modified example (Synonyms property now has a private setter):
https://riptutorial.com/ 195
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.
https://riptutorial.com/ 196
Chapter 36: Comments and regions
Examples
Comments
Using comments in your projects is a handy way of leaving explanations of your design choices,
and should aim to make your (or someone else's) life easier when maintaining or adding to the
code.
System.Console.ReadLine();
}
https://riptutorial.com/ 197
}
Regions
A region is a collapsible block of code, that can help with the readability and organisation of your
code.
NOTE: StyleCop's rule SA1124 DoNotUseRegions discourages use of regions. They are usually a
sign of badly organized code, as C# includes partial classes and other features which make
regions obsolete.
class Program
{
#region Application entry point
static void Main(string[] args)
{
PrintHelloWorld();
System.Console.ReadLine();
}
#endregion
#region My method
private static void PrintHelloWorld()
{
System.Console.WriteLine("Hello, World!");
}
#endregion
}
When the above code is view in an IDE, you will be able to collapse and expand the code using
the + and - symbols.
Expanded
https://riptutorial.com/ 198
Collapsed
Documentation comments
XML documentation comments can be used to provide API documentation that can be easily
processed by tools:
/// <summary>
/// A helper class for validating method arguments.
/// </summary>
public static class Precondition
{
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> with the parameter
/// name set to <c>paramName</c> if <c>value</c> does not satisfy the
/// <c>predicate</c> specified.
/// </summary>
/// <typeparam name="T">
/// The type of the argument checked
/// </typeparam>
/// <param name="value">
/// The argument to be checked
/// </param>
/// <param name="predicate">
/// The predicate the value is required to satisfy
/// </param>
/// <param name="paramName">
/// The parameter name to be passed to the
/// <see cref="ArgumentOutOfRangeException"/>.
/// </param>
/// <returns>The value specified</returns>
public static T Satisfies<T>(T value, Func<T, bool> predicate, string paramName)
{
if (!predicate(value))
throw new ArgumentOutOfRangeException(paramName);
return value;
}
}
https://riptutorial.com/ 199
Read Comments and regions online: https://riptutorial.com/csharp/topic/5346/comments-and-
regions
https://riptutorial.com/ 200
Chapter 37: Common String Operations
Examples
Splitting a String by specific character
Substring returns the string up from a given index, or between two indexes (both inclusive).
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.Trim()
string q = "{(Hi!*";
string r = q.Trim( '(', '*', '{' ); // "Hi!"
https://riptutorial.com/ 201
String.TrimStart() and String.TrimEnd()
string q = "{(Hi*";
string r = q.TrimStart( '{' ); // "(Hi*"
string s = q.TrimEnd( '*' ); // "{(Hi"
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
string s = "Foo";
string paddedLeft = s.PadLeft(5); // paddedLeft = " Foo" (pads with spaces by default)
string paddedRight = s.PadRight(6, '+'); // paddedRight = "Foo+++"
string noPadded = s.PadLeft(2); // noPadded = "Foo" (original string is never
shortened)
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.
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.
https://riptutorial.com/ 202
Output : a|b|c
Output : Ram_is_a_boy
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;
Visual Basic has Left, Right, and Mid functions that returns characters from the Left, Right, and
https://riptutorial.com/ 203
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:
/// <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;
/// <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 )
{
// Handle possible Null or numeric stringparam being passed
stringparam += string.Empty;
https://riptutorial.com/ 204
// Validate numchars parameter
if (startindex > stringparam.Length)
startindex = stringparam.Length;
/// <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;
}
}
bool result;
https://riptutorial.com/ 205
result = String.IsNullOrEmpty(nullString); // true
result = String.IsNullOrEmpty(emptyString); // true
result = String.IsNullOrEmpty(whitespaceString); // false
result = String.IsNullOrEmpty(tabString); // false
result = String.IsNullOrEmpty(newlineString); // false
result = String.IsNullOrEmpty(nonEmptyString); // false
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 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
**********/
https://riptutorial.com/ 206
var Number = 15;
Console.WriteLine(Convert.ToString(Number, 16)); //OUTPUT : f
Result:
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:
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).
https://riptutorial.com/ 207
work. A font may contain multiple alternative glyphs for the same grapheme, too.
Which means, if you just reverse a valid string like Les Misérables, which can look like this
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.
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();
https://riptutorial.com/ 208
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.)...
Using the System.String.Replace method, you can replace part of a string with another string.
This method can also be used to remove part of a string, using the String.Empty field:
The System.String class supports a number of methods to convert between uppercase and
lowercase characters in a string.
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:
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.
The System.String.Join method allows to concatenate all elements in a string array, using a
specified separator between each element:
https://riptutorial.com/ 209
string singleString = String.Join(",", words); // singleString = "One,Two,Three,Four"
String Concatenation
String Concatenation can be done by using the System.String.Concat method, or (much easier)
using the + operator:
https://riptutorial.com/ 210
Chapter 38: Conditional Statements
Examples
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.
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.
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.
https://riptutorial.com/ 211
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:
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!.
Switch statements
A switch statement allows a variable to be tested for equality against a list of values. Each value is
called a case, and the variable being switched on is checked for each switch case.
A switch statement is often more concise and understandable than if...else if... else..
statements when testing multiple possible values for a single variable.
Syntax is as follows
switch(expression) {
case constant-expression:
statement(s);
break;
case constant-expression:
statement(s);
break;
https://riptutorial.com/ 212
}
there are sevaral things that have to consider while using the switch statement
• The expression used in a switch statement must have an integral or enumerated type, or be
of a class type in which the class has a single conversion function to an integral or
enumerated type.
• You can have any number of case statements within a switch. Each case is followed by the
value to be compared to and a colon. The values to compare to have to be unique within
each switch statement.
• A switch statement can have an optional default case. The default case can be used for
performing a task when none of the cases is true.
• Each case has to end with a break statement unless it is an empty statement. In that case
execution will continue at the case below it. The break statement can also be omitted when a
return, throw or goto case statement is used.
switch (grade)
{
case 'A':
Console.WriteLine("Excellent!");
break;
case 'B':
case 'C':
Console.WriteLine("Well done");
break;
case 'D':
Console.WriteLine("You passed");
break;
case 'F':
Console.WriteLine("Better try again");
break;
default:
Console.WriteLine("Invalid grade");
break;
}
is exactly equivalent to
in other words, the conditions inside the "if" statement just form an ordinary Boolean expression.
https://riptutorial.com/ 213
A common mistake when writing conditional statements is to explicitly compare to true and false:
https://riptutorial.com/ 214
Chapter 39: Constructors and Finalizers
Introduction
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.
Remarks
C# does not actually have destructors, but rather Finalizers which use C++ style destructor syntax.
Specifying a destructor overrides the Object.Finalize() method which cannot be called directly.
Unlike other languages with similar syntax, these methods are not called when objects go out of
scope, but are called when the Garbage Collector runs, which occurs under certain conditions. As
such, they are not guaranteed to run in any particular order.
Finalizers should be responsible for cleaning up unmanaged resources only (pointers acquired via
the Marshal class, received through p/Invoke (system calls) or raw pointers used within unsafe
blocks). To clean up managed resources, please review IDisposable, the Dispose pattern and the
using statement.
Examples
Default Constructor
The definition of any constructor for the type will suppress the default constructor generation. If the
type were defined as follows:
https://riptutorial.com/ 215
public class Animal
{
public Animal(string name) {}
}
// 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:
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.
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:
https://riptutorial.com/ 216
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");
}
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.
Animal.Yawn();
Animal initialized
https://riptutorial.com/ 217
Yawn!
Singleton example:
static SessionManager()
{
Instance = new SessionManager();
}
}
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.
In this case, instantiating a Mammal by calling new Mammal("George the Cat") will print
View Demo
Calling a different constructor of the base class is done by placing : base(args) between the
constructor's signature and its body:
https://riptutorial.com/ 218
Console.WriteLine(name + " is a mammal.");
}
}
View Demo
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!");
}
}
private SingletonClass()
{
// Put custom constructor code here
}
}
https://riptutorial.com/ 219
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.
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:
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.
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:
https://riptutorial.com/ 220
private readonly AnotherBase _obj;
}
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.
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);
}
Animal<Object>.Yawn();
Animal<String>.Yawn();
System.Object
System.String
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 exception.
https://riptutorial.com/ 221
public class Animal
{
static Animal()
{
Console.WriteLine("Static ctor");
throw new Exception();
}
try
{
Animal.Yawn();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
try
{
Animal.Yawn();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Static ctor
[...]
where you can see that the actual constructor is only executed once, and the exception is re-used.
Shall the property value's assignment be executed before or after the class' constructor?
public TestClass()
{
if (TestProperty == 1)
{
Console.WriteLine("Shall this be executed?");
https://riptutorial.com/ 222
}
if (TestProperty == 2)
{
Console.WriteLine("Or shall this be executed");
}
}
}
In the example above, shall the TestProperty value be 1 in the class' constructor or after the class
constructor?
Will be executed after the constructor is run. However, initializing the property value in the class'
property in C# 6.0 like this:
public TestClass()
{
}
}
public TestClass()
{
if (TestProperty == 1)
{
Console.WriteLine("Shall this be executed?");
}
if (TestProperty == 2)
{
Console.WriteLine("Or shall this be executed");
}
}
}
https://riptutorial.com/ 223
var testInstance = new TestClass() { TestProperty = 1 };
Console.WriteLine(testInstance.TestProperty); //resulting in 1
}
Final result:
Explanation:
The TestProperty value will first be assigned as 2, then the TestClass constructor will be run,
resulting in printing of
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"
https://riptutorial.com/ 224
Chapter 40: Creating a Console Application
using a Plain-Text Editor and the C# Compiler
(csc.exe)
Examples
Creating a Console application using a Plain-Text Editor and the C# Compiler
In order to use a plain-text editor to create a Console application that is written in C#, you'll need
the C# Compiler. The C# Compiler (csc.exe), can be found at the following location:
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe
N.B. Depending upon which version of the .NET Framework that is installed on your system, you
may need to change the path above, accordingly.
1. Open the Run dialog, by using the keyboard shortcut Windows Key + R
2. Type notepad, then hit Enter
3. Paste the example code below, into Notepad
4. Save the file as ConsoleApp.cs, by going to File → Save As..., then entering ConsoleApp.cs in
the 'File Name' text field, then selecting All Files as the file-type.
5. Click Save
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /t:exe
/out:"C:\Users\yourUserName\Documents\ConsoleApp.exe"
"C:\Users\yourUserName\Documents\ConsoleApp.cs"
Now, go back to where you originally saved your ConsoleApp.cs file. You should now see an
executable file (ConsoleApp.exe). Double-click ConsoleApp.exe to open it.
https://riptutorial.com/ 225
That's it! Your console application has been compiled. An executable file has been created and
you now have a working Console app.
using System;
namespace ConsoleApp
{
class Program
{
private static string input = String.Empty;
DisplayGreeting:
{
Console.WriteLine("Hello! What is your name?");
input = Console.ReadLine();
if (input.Length >= 1)
{
Console.WriteLine(
"Hello, " +
input +
", enter 'Exit' at any time to exit this app.");
goto AwaitFurtherInstruction;
}
else
{
goto DisplayGreeting;
}
}
AwaitFurtherInstruction:
{
input = Console.ReadLine();
if(input.ToLower() == "exit")
{
input = String.Empty;
Environment.Exit(0);
}
else
{
goto AwaitFurtherInstruction;
}
}
}
}
}
Read Creating a Console Application using a Plain-Text Editor and the C# Compiler (csc.exe)
online: https://riptutorial.com/csharp/topic/6676/creating-a-console-application-using-a-plain-text-
editor-and-the-csharp-compiler--csc-exe-
https://riptutorial.com/ 226
Chapter 41: Creating Own MessageBox in
Windows Form Application
Introduction
First we need to know what a MessageBox is...
The MessageBox control displays a message with specified text, and can be customised by
specifying a custom image, title and button sets (These button sets allow the user to choose more
than a basic yes/no answer).
By creating our own MessageBox we can re-use that MessageBox Control in any new applications
just by using the generated dll, or copying the file containing the class.
Syntax
• 'static DialogResult result = DialogResult.No; //DialogResult is returned by dialogs after
dismissal.'
Examples
Creating Own MessageBox Control.
To create our own MessageBox control simply follow the guide below...
2. Go to the toolbar at the top and click File -> New Project --> Windows Forms Application -->
Give the project a name and then click ok.
3. Once loaded, drag and drop a button control from the Toolbox (found on the left) onto the
form (as shown below).
https://riptutorial.com/ 227
4. Double click the button and the Integrated Development Environment will automatically
generate the click event handler for you.
5. Edit the code for the form so that it looks like the following (You can right-click the form and
click Edit Code):
namespace MsgBoxExample {
public partial class MsgBoxExampleForm : Form {
//Constructor, called when the class is initialised.
public MsgBoxExampleForm() {
InitializeComponent();
}
6. Solution Explorer -> Right Click on your project --> Add --> Windows Form and set the name
as "CustomMsgBox.cs"
7. Drag in a button & label control from the Toolbox to the form (It'll look something like the
form below after doing it):
https://riptutorial.com/ 228
8. Now write out the code below into the newly created form:
9. Now run the program by just pressing F5 Key. Congratulations, you've made a reusable
control.
To find your existing .cs files, right click on the project in your instance of Visual Studio, and click
Open Folder in File Explorer.
1. Visual Studio --> Your current project (Windows Form) --> Solution Explorer --> Project
Name --> Right Click --> Add --> Existing Item --> Then locate your existing .cs file.
2. Now there's one last thing to do in order to use the control. Add a using statement to your
code, so that your assembly knows about its dependencies.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
.
.
.
using CustomMsgBox; //Here's the using statement for our dependency.
https://riptutorial.com/ 229
3. To display the messagebox, simply use the following...
https://riptutorial.com/ 230
Chapter 42: Creational Design Patterns
Remarks
The creational patterns aim to separate a system from how its objects are created, composed, and
represented. They increase the system's flexibility in terms of the what, who, how, and when of
object creation. Creational patterns encapsulate the knowledge about which classes a system
uses, but they hide the details of how the instances of these classes are created and put together.
Programmers have come to realize that composing systems with inheritance makes those
systems too rigid. The creational patterns are designed to break this close coupling.
Examples
Singleton Pattern
The Singleton pattern is designed to restrict creation of a class to exactly one single instance.
This pattern is used in a scenario where it makes sense to have only one of something, such as:
• a single class that orchestrates other objects' interactions, ex. Manager class
• or one class that represents a unique, single resource, ex. Logging component
One of the most common ways to implement the Singleton pattern is via a static factory method
such as a CreateInstance() or GetInstance() (or a static property in C#, Instance), which is then
designed to always return the same instance.
The first call to the method or property creates and returns the Singleton instance. Thereafter, the
method always returns the same instance. This way, there is only ever one instance of the
singleton object.
Preventing creation of instances via new can be accomplished by making the class constructor(s)
private.
class Singleton
{
// Because the _instance member is made private, the only way to get the single
// instance is via the static Instance property below. This can also be similarly
// achieved with a GetInstance() method instead of the property.
private static Singleton _instance = null;
https://riptutorial.com/ 231
public static Singleton Instance
{
get
{
// The first call will create the one and only instance.
if (_instance == null)
{
_instance = new Singleton();
}
// Every call afterwards will return the single instance created above.
return _instance;
}
}
}
To illustrate this pattern further, the code below checks whether an identical instance of the
Singleton is returned when the Instance property is called more than once.
class Program
{
static void Main(string[] args)
{
Singleton s1 = Singleton.Instance;
Singleton s2 = Singleton.Instance;
// Both Singleton objects above should now reference the same Singleton instance.
if (Object.ReferenceEquals(s1, s2))
{
Console.WriteLine("Singleton is working");
}
else
{
// Otherwise, the Singleton Instance property is returning something
// other than the unique, single instance when called.
Console.WriteLine("Singleton is broken");
}
}
}
To see more examples, including how to make this thread-safe, visit: Singleton Implementation
Singletons are conceptually similar to a global value, and cause similar design flaws and
concerns. Because of this, the Singleton pattern is widely regarded as an anti-pattern.
Visit "What is so bad about Singletons?" for more information on the problems that arise with their
use.
In C#, you have the ability to make a class static, which makes all members static, and the class
cannot be instantiated. Given this, it is common to see static classes used in place of the Singleton
pattern.
For key differences between the two, visit C# Singleton Pattern Versus Static Class.
https://riptutorial.com/ 232
Factory Method pattern
Factory Method is one of creational design patterns. It is used to deal with the problem of creating
objects without specifying exact result type. This document will teach you how to use Factory
Method DP properly.
Let me explain the idea of it to you on a simple example. Imagine you're working in a factory that
produces three types of devices - Ammeter, Voltmeter and resistance meter. You are writing a
program for a central computer that will create selected device, but you don't know final decision
of your boss on what to produce.
Let's create an interface IDevice with some common functions that all devices have:
Now, we can create classes that represent our devices. Those classes must implement IDevice
interface:
https://riptutorial.com/ 233
Now we have to define factory method. Let's create DeviceFactory class with static method inside:
device = DeviceFactory.CreateDevice(Device.VOLT);
device.TurnOn();
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
device.TurnOff();
Console.WriteLine();
device = DeviceFactory.CreateDevice(Device.OHM);
device.TurnOn();
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
Console.WriteLine(device.Measure());
device.TurnOff();
Console.WriteLine();
}
}
https://riptutorial.com/ 234
This is the example output you might see after running this code:
36
33
43
24
102
-61
85
138
36
723828
368536
685412
800266
578595
Builder Pattern
Separate the construction of a complex object from its representation so that the same
construction process can create different representations and and provides a high level of control
over the assembly of the objects.
In this example demonstrates the Builder pattern in which different vehicles are assembled in a
step-by-step fashion. The Shop uses VehicleBuilders to construct a variety of Vehicles in a series
https://riptutorial.com/ 235
of sequential steps.
using System;
using System.Collections.Generic;
namespace GangOfFour.Builder
{
/// <summary>
/// MainApp startup class for Real-World
/// Builder Design Pattern.
/// </summary>
public class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
VehicleBuilder builder;
/// <summary>
/// The 'Director' class
/// </summary>
class Shop
{
// Builder uses a complex series of steps
public void Construct(VehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
}
}
/// <summary>
/// The 'Builder' abstract class
/// </summary>
abstract class VehicleBuilder
{
https://riptutorial.com/ 236
protected Vehicle vehicle;
/// <summary>
/// The 'ConcreteBuilder1' class
/// </summary>
class MotorCycleBuilder : VehicleBuilder
{
public MotorCycleBuilder()
{
vehicle = new Vehicle("MotorCycle");
}
/// <summary>
/// The 'ConcreteBuilder2' class
/// </summary>
class CarBuilder : VehicleBuilder
{
public CarBuilder()
{
vehicle = new Vehicle("Car");
}
https://riptutorial.com/ 237
public override void BuildEngine()
{
vehicle["engine"] = "2500 cc";
}
/// <summary>
/// The 'ConcreteBuilder3' class
/// </summary>
class ScooterBuilder : VehicleBuilder
{
public ScooterBuilder()
{
vehicle = new Vehicle("Scooter");
}
/// <summary>
/// The 'Product' class
/// </summary>
class Vehicle
{
private string _vehicleType;
private Dictionary<string,string> _parts =
new Dictionary<string,string>();
// Constructor
public Vehicle(string vehicleType)
{
this._vehicleType = vehicleType;
https://riptutorial.com/ 238
}
// Indexer
public string this[string key]
{
get { return _parts[key]; }
set { _parts[key] = value; }
}
Output
Prototype Pattern
Specify the kind of objects to create using a prototypical instance, and create new objects by
copying this prototype.
In this example demonstrates the Prototype pattern in which new Color objects are created by
copying pre-existing, user-defined Colors of the same type.
using System;
using System.Collections.Generic;
https://riptutorial.com/ 239
namespace GangOfFour.Prototype
{
/// <summary>
/// MainApp startup class for Real-World
/// Prototype Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
static void Main()
{
ColorManager colormanager = new ColorManager();
/// <summary>
/// The 'Prototype' abstract class
/// </summary>
abstract class ColorPrototype
{
public abstract ColorPrototype Clone();
}
/// <summary>
/// The 'ConcretePrototype' class
/// </summary>
class Color : ColorPrototype
{
private int _red;
private int _green;
private int _blue;
// Constructor
public Color(int red, int green, int blue)
{
this._red = red;
this._green = green;
this._blue = blue;
}
https://riptutorial.com/ 240
// Create a shallow copy
public override ColorPrototype Clone()
{
Console.WriteLine(
"Cloning color RGB: {0,3},{1,3},{2,3}",
_red, _green, _blue);
/// <summary>
/// Prototype manager
/// </summary>
class ColorManager
{
private Dictionary<string, ColorPrototype> _colors =
new Dictionary<string, ColorPrototype>();
// Indexer
public ColorPrototype this[string key]
{
get { return _colors[key]; }
set { _colors.Add(key, value); }
}
}
}
Output:
Provide an interface for creating families of related or dependent objects without specifying their
concrete classes.
In this example demonstrates the creation of different animal worlds for a computer game using
different factories. Although the animals created by the Continent factories are different, the
interactions among the animals remain the same.
using System;
namespace GangOfFour.AbstractFactory
{
/// <summary>
/// MainApp startup class for Real-World
/// Abstract Factory Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
https://riptutorial.com/ 241
/// Entry point into console application.
/// </summary>
public static void Main()
{
// Create and run the African animal world
ContinentFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld(africa);
world.RunFoodChain();
/// <summary>
/// The 'AbstractFactory' abstract class
/// </summary>
abstract class ContinentFactory
{
public abstract Herbivore CreateHerbivore();
public abstract Carnivore CreateCarnivore();
}
/// <summary>
/// The 'ConcreteFactory1' class
/// </summary>
class AfricaFactory : ContinentFactory
{
public override Herbivore CreateHerbivore()
{
return new Wildebeest();
}
public override Carnivore CreateCarnivore()
{
return new Lion();
}
}
/// <summary>
/// The 'ConcreteFactory2' class
/// </summary>
class AmericaFactory : ContinentFactory
{
public override Herbivore CreateHerbivore()
{
return new Bison();
}
public override Carnivore CreateCarnivore()
{
return new Wolf();
}
}
/// <summary>
/// The 'AbstractProductA' abstract class
https://riptutorial.com/ 242
/// </summary>
abstract class Herbivore
{
}
/// <summary>
/// The 'AbstractProductB' abstract class
/// </summary>
abstract class Carnivore
{
public abstract void Eat(Herbivore h);
}
/// <summary>
/// The 'ProductA1' class
/// </summary>
class Wildebeest : Herbivore
{
}
/// <summary>
/// The 'ProductB1' class
/// </summary>
class Lion : Carnivore
{
public override void Eat(Herbivore h)
{
// Eat Wildebeest
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}
/// <summary>
/// The 'ProductA2' class
/// </summary>
class Bison : Herbivore
{
}
/// <summary>
/// The 'ProductB2' class
/// </summary>
class Wolf : Carnivore
{
public override void Eat(Herbivore h)
{
// Eat Bison
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}
/// <summary>
/// The 'Client' class
/// </summary>
class AnimalWorld
{
private Herbivore _herbivore;
private Carnivore _carnivore;
https://riptutorial.com/ 243
// Constructor
public AnimalWorld(ContinentFactory factory)
{
_carnivore = factory.CreateCarnivore();
_herbivore = factory.CreateHerbivore();
}
Output:
https://riptutorial.com/ 244
Chapter 43: Cryptography
(System.Security.Cryptography)
Examples
Modern Examples of Symmetric Authenticated Encryption of a string
Cryptography is something very hard and after spending a lot of time reading different examples
and seeing how easy it is to introduce some form of vulnerability I found an answer originally
written by @jbtule that I think is very good. Enjoy reading:
"The general best practice for symmetric encryption is to use Authenticated Encryption with
Associated Data (AEAD), however this isn't a part of the standard .net crypto libraries. So the first
example uses AES256 and then HMAC256, a two step Encrypt then MAC, which requires more
overhead and more keys.
The second example uses the simpler practice of AES256-GCM using the open source Bouncy
Castle (via nuget).
Both examples have a main function that takes secret message string, key(s) and an optional non-
secret payload and return and authenticated encrypted string optionally prepended with the non-
secret data. Ideally you would use these with 256bit key(s) randomly generated see NewKey().
Both examples also have a helper methods that use a string password to generate the keys.
These helper methods are provided as a convenience to match up with other examples, however
they are far less secure because the strength of the password is going to be far weaker than a 256
bit key.
Update: Added byte[] overloads, and only the Gist has the full formatting with 4 spaces indent
and api docs due to StackOverflow answer limits."
/*
* This work (Modern Encryption of a String C#, by James Tuley),
* identified by James Tuley, is free of known copyright restrictions.
* https://gist.github.com/4336842
* http://creativecommons.org/publicdomain/mark/1.0/
*/
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Encryption
{
public static class AESThenHMAC
https://riptutorial.com/ 245
{
private static readonly RandomNumberGenerator Random = RandomNumberGenerator.Create();
/// <summary>
/// Helper that generates a random key on each call.
/// </summary>
/// <returns></returns>
public static byte[] NewKey()
{
var key = new byte[KeyBitSize / 8];
Random.GetBytes(key);
return key;
}
/// <summary>
/// Simple Encryption (AES) then Authentication (HMAC) for a UTF8 Message.
/// </summary>
/// <param name="secretMessage">The secret message.</param>
/// <param name="cryptKey">The crypt key.</param>
/// <param name="authKey">The auth key.</param>
/// <param name="nonSecretPayload">(Optional) Non-Secret Payload.</param>
/// <returns>
/// Encrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">Secret Message
Required!;secretMessage</exception>
/// <remarks>
/// Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize +
HMac-Tag(32)) * 1.33 Base64
/// </remarks>
public static string SimpleEncrypt(string secretMessage, byte[] cryptKey, byte[] authKey,
byte[] nonSecretPayload = null)
{
if (string.IsNullOrEmpty(secretMessage))
throw new ArgumentException("Secret Message Required!", "secretMessage");
/// <summary>
/// Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message.
/// </summary>
/// <param name="encryptedMessage">The encrypted message.</param>
/// <param name="cryptKey">The crypt key.</param>
/// <param name="authKey">The auth key.</param>
/// <param name="nonSecretPayloadLength">Length of the non secret payload.</param>
/// <returns>
/// Decrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">Encrypted Message
https://riptutorial.com/ 246
Required!;encryptedMessage</exception>
public static string SimpleDecrypt(string encryptedMessage, byte[] cryptKey, byte[]
authKey,
int nonSecretPayloadLength = 0)
{
if (string.IsNullOrWhiteSpace(encryptedMessage))
throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
/// <summary>
/// Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message
/// using Keys derived from a Password (PBKDF2).
/// </summary>
/// <param name="secretMessage">The secret message.</param>
/// <param name="password">The password.</param>
/// <param name="nonSecretPayload">The non secret payload.</param>
/// <returns>
/// Encrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">password</exception>
/// <remarks>
/// Significantly less secure than using random binary keys.
/// Adds additional non secret payload for key generation parameters.
/// </remarks>
public static string SimpleEncryptWithPassword(string secretMessage, string password,
byte[] nonSecretPayload = null)
{
if (string.IsNullOrEmpty(secretMessage))
throw new ArgumentException("Secret Message Required!", "secretMessage");
/// <summary>
/// Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message
/// using keys derived from a password (PBKDF2).
/// </summary>
/// <param name="encryptedMessage">The encrypted message.</param>
/// <param name="password">The password.</param>
/// <param name="nonSecretPayloadLength">Length of the non secret payload.</param>
/// <returns>
/// Decrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">Encrypted Message
Required!;encryptedMessage</exception>
/// <remarks>
/// Significantly less secure than using random binary keys.
/// </remarks>
public static string SimpleDecryptWithPassword(string encryptedMessage, string password,
int nonSecretPayloadLength = 0)
{
if (string.IsNullOrWhiteSpace(encryptedMessage))
throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
https://riptutorial.com/ 247
var plainText = SimpleDecryptWithPassword(cipherText, password, nonSecretPayloadLength);
return plainText == null ? null : Encoding.UTF8.GetString(plainText);
}
byte[] cipherText;
byte[] iv;
//Use random IV
aes.GenerateIV();
iv = aes.IV;
cipherText = cipherStream.ToArray();
}
https://riptutorial.com/ 248
binaryWriter.Write(nonSecretPayload);
//Prepend IV
binaryWriter.Write(iv);
//Write Ciphertext
binaryWriter.Write(cipherText);
binaryWriter.Flush();
https://riptutorial.com/ 249
BlockSize = BlockBitSize,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
})
{
byte[] cryptKey;
byte[] authKey;
//Use Random Salt to prevent pre-generated weak password attacks.
using (var generator = new Rfc2898DeriveBytes(password, SaltBitSize / 8, Iterations))
{
var salt = generator.Salt;
//Generate Keys
cryptKey = generator.GetBytes(KeyBitSize / 8);
https://riptutorial.com/ 250
payloadIndex += salt.Length;
}
//Generate Keys
authKey = generator.GetBytes(KeyBitSize / 8);
byte[] cryptKey;
byte[] authKey;
https://riptutorial.com/ 251
/*
* This work (Modern Encryption of a String C#, by James Tuley),
* identified by James Tuley, is free of known copyright restrictions.
* https://gist.github.com/4336842
* http://creativecommons.org/publicdomain/mark/1.0/
*/
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Encryption
{
/// <summary>
/// Helper that generates a random new key on each call.
/// </summary>
/// <returns></returns>
public static byte[] NewKey()
{
var key = new byte[KeyBitSize / 8];
Random.NextBytes(key);
return key;
}
/// <summary>
/// Simple Encryption And Authentication (AES-GCM) of a UTF8 string.
/// </summary>
/// <param name="secretMessage">The secret message.</param>
/// <param name="key">The key.</param>
/// <param name="nonSecretPayload">Optional non-secret payload.</param>
/// <returns>
/// Encrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">Secret Message
Required!;secretMessage</exception>
/// <remarks>
/// Adds overhead of (Optional-Payload + BlockSize(16) + Message + HMac-Tag(16)) * 1.33
Base64
/// </remarks>
public static string SimpleEncrypt(string secretMessage, byte[] key, byte[]
https://riptutorial.com/ 252
nonSecretPayload = null)
{
if (string.IsNullOrEmpty(secretMessage))
throw new ArgumentException("Secret Message Required!", "secretMessage");
/// <summary>
/// Simple Decryption & Authentication (AES-GCM) of a UTF8 Message
/// </summary>
/// <param name="encryptedMessage">The encrypted message.</param>
/// <param name="key">The key.</param>
/// <param name="nonSecretPayloadLength">Length of the optional non-secret
payload.</param>
/// <returns>Decrypted Message</returns>
public static string SimpleDecrypt(string encryptedMessage, byte[] key, int
nonSecretPayloadLength = 0)
{
if (string.IsNullOrEmpty(encryptedMessage))
throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
/// <summary>
/// Simple Encryption And Authentication (AES-GCM) of a UTF8 String
/// using key derived from a password (PBKDF2).
/// </summary>
/// <param name="secretMessage">The secret message.</param>
/// <param name="password">The password.</param>
/// <param name="nonSecretPayload">The non secret payload.</param>
/// <returns>
/// Encrypted Message
/// </returns>
/// <remarks>
/// Significantly less secure than using random binary keys.
/// Adds additional non secret payload for key generation parameters.
/// </remarks>
public static string SimpleEncryptWithPassword(string secretMessage, string password,
byte[] nonSecretPayload = null)
{
if (string.IsNullOrEmpty(secretMessage))
throw new ArgumentException("Secret Message Required!", "secretMessage");
/// <summary>
/// Simple Decryption and Authentication (AES-GCM) of a UTF8 message
/// using a key derived from a password (PBKDF2)
/// </summary>
/// <param name="encryptedMessage">The encrypted message.</param>
https://riptutorial.com/ 253
/// <param name="password">The password.</param>
/// <param name="nonSecretPayloadLength">Length of the non secret payload.</param>
/// <returns>
/// Decrypted Message
/// </returns>
/// <exception cref="System.ArgumentException">Encrypted Message
Required!;encryptedMessage</exception>
/// <remarks>
/// Significantly less secure than using random binary keys.
/// </remarks>
public static string SimpleDecryptWithPassword(string encryptedMessage, string password,
int nonSecretPayloadLength = 0)
{
if (string.IsNullOrWhiteSpace(encryptedMessage))
throw new ArgumentException("Encrypted Message Required!", "encryptedMessage");
//Assemble Message
using (var combinedStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(combinedStream))
{
//Prepend Authenticated Payload
binaryWriter.Write(nonSecretPayload);
//Prepend Nonce
binaryWriter.Write(nonce);
//Write Cipher Text
binaryWriter.Write(cipherText);
}
https://riptutorial.com/ 254
return combinedStream.ToArray();
}
}
//Grab Nonce
var nonce = cipherReader.ReadBytes(NonceBitSize / 8);
try
{
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
}
catch (InvalidCipherTextException)
{
//Return null if it doesn't authenticate
return null;
}
return plainText;
}
https://riptutorial.com/ 255
if (secretMessage == null || secretMessage.Length == 0)
throw new ArgumentException("Secret Message Required!", "secretMessage");
generator.Init(
PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()),
salt,
Iterations);
//Generate Key
var key = (KeyParameter)generator.GenerateDerivedMacParameters(KeyBitSize);
generator.Init(
PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()),
salt,
Iterations);
//Generate Key
var key = (KeyParameter)generator.GenerateDerivedMacParameters(KeyBitSize);
You can improve the security for data transit or storing by implementing encrypting techniques.
https://riptutorial.com/ 256
Basically there are two approaches when using System.Security.Cryptography: symmetric and
asymmetric.
Symmetric Encryption
This method uses a private key in order to perform the data transformation.
Pros:
• Symmetric algorithms consume less resources and are faster than asymmetric ones.
• The amount of data you can encrypt is unlimited.
Cons:
• Encryption and decryption use the same key. Someone will be able to decrypt your data if
the key is compromised.
• You could end up with many different secret keys to manage if you choose to use a different
secret key for different data.
Asymmetric Encryption
This method uses a combination of public and private keys in order to perform the data
transformation.
Pros:
• It uses larger keys than symmetric algorithms, thus they are less susceptible to being
cracked by using brute force.
• It is easier to guarantee who is able to encrypt and decrypt the data because it relies on two
keys (public and private).
Cons:
• There is a limit on the amount of data that you can encrypt. The limit is different for each
algorithm and is typically proportional with the key size of the algorithm. For example, an
RSACryptoServiceProvider object with a key length of 1,024 bits can only encrypt a
https://riptutorial.com/ 257
message that is smaller than 128 bytes.
• Asymmetric algorithms are very slow in comparison to symmetric algorithms.
Password Hashing
Passwords should never be stored as plain text! They should be hashed with a randomly
generated salt (to defend against rainbow table attacks) using a slow password hashing algorithm.
A high number of iterations (> 10k) can be used to slow down brute force attacks. A delay of
~100ms is acceptable to a user logging in, but makes breaking a long password difficult. When
choosing a number of iterations you should use the maximum tolerable value for your application
and increase it as computer performance improves. You will also need to consider stopping
repeated requests which could be used as a DoS attack.
When hashing for the first time a salt can be generated for you, the resulting hash and salt can
then be stored to a file.
Checking an existing users password, read their hash and salt from a file and compare to the hash
of the entered password
The following code sample demonstrates a quick and easy means of encrypting and decrypting
files using the AES symmetric encryption algorithm.
https://riptutorial.com/ 258
The code randomly generates the Salt and Initialization Vectors each time a file is encrypted,
meaning that encrypting the same file with the same password will always lead to different output.
The salt and IV are written to the output file so that only the password is required to decrypt it.
public static void ProcessFile(string inputPath, string password, bool encryptMode, string
outputPath)
{
using (var cypher = new AesManaged())
using (var fsIn = new FileStream(inputPath, FileMode.Open))
using (var fsOut = new FileStream(outputPath, FileMode.Create))
{
const int saltLength = 256;
var salt = new byte[saltLength];
var iv = new byte[cypher.BlockSize / 8];
if (encryptMode)
{
// Generate random salt and IV, then write them to file
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(salt);
rng.GetBytes(iv);
}
fsOut.Write(salt, 0, salt.Length);
fsOut.Write(iv, 0, iv.Length);
}
else
{
// Read the salt and IV from the file
fsIn.Read(salt, 0, saltLength);
fsIn.Read(iv, 0, iv.Length);
}
There are times when the framework's Random() class may not be considered random enough,
given that it is based on a psuedo-random number generator. The framework's Crypto classes do,
however, provide something more robust in the form of RNGCryptoServiceProvider.
The following code samples demonstrate how to generate Cryptographically Secure byte arrays,
strings and numbers.
https://riptutorial.com/ 259
Random Byte Array
Random String
In order to provide both security AND performance, a hybrid approach can be taken. This entails
https://riptutorial.com/ 260
the cryptographically random generation of a key and initialization vector for Symmetric
encryption. These values are then encrypted using an Asymmetric algorithm and written to the
output file, before being used to encrypt the source data Symmetrically and appending it to the
output.
This approach provides a high degree of both performance and security, in that the data is
encrypted using a symmetric algorithm (fast) and the key and iv, both randomly generated
(secure) are encrypted by an asymmetric algorithm (secure). It also has the added advantage that
the same payload encrypted on different occasions will have very different cyphertext, because
the symmetric keys are randomly generated each time.
The following class demonstrates asymmetric encryption of strings and byte arrays, as well as
hybrid file encryption.
#endregion
https://riptutorial.com/ 261
}
#endregion
// Symmetrically encrypt the data and write it to the file, along with the
encrypted key and iv
using (var cypherKey = symmetricCypher.CreateEncryptor(key, iv))
using (var fsIn = new FileStream(inputFilePath, FileMode.Open))
using (var fsOut = new FileStream(outputFilePath, FileMode.Create))
using (var cs = new CryptoStream(fsOut, cypherKey, CryptoStreamMode.Write))
{
fsOut.Write(bufLen,0, bufLen.Length);
fsOut.Write(buf, 0, buf.Length);
fsIn.CopyTo(cs);
}
}
}
https://riptutorial.com/ 262
fsIn.Read(buf, 0, buf.Length);
var bufLen = BitConverter.ToInt32(buf, 0);
// Read the encrypted key and IV data from the file and decrypt using the
asymmetric algorithm
buf = new byte[bufLen];
fsIn.Read(buf, 0, buf.Length);
buf = DecryptData(buf, privateKey);
#endregion
https://riptutorial.com/ 263
public static void WritePrivateKey(string privateKeyFilePath, string privateKey, string
password)
{
var salt = Encoding.UTF8.GetBytes(SymmetricSalt);
using (var cypher = new AesManaged())
{
var pdb = new Rfc2898DeriveBytes(password, salt);
var key = pdb.GetBytes(cypher.KeySize / 8);
var iv = pdb.GetBytes(cypher.BlockSize / 8);
#endregion
}
Example of use:
if (!File.Exists(privateKeyPath))
{
var keys = AsymmetricProvider.GenerateNewKeyPair(2048);
AsymmetricProvider.WritePublicKey(publicKeyPath, keys.PublicKey);
AsymmetricProvider.WritePrivateKey(privateKeyPath, keys.PrivateKey,
privateKeyPassword);
}
if (source.Length != dest.Length)
throw new Exception("Length does not match");
https://riptutorial.com/ 264
Read Cryptography (System.Security.Cryptography) online:
https://riptutorial.com/csharp/topic/2988/cryptography--system-security-cryptography-
https://riptutorial.com/ 265
Chapter 44: Data Annotation
Examples
DisplayNameAttribute (display attribute)
DisplayName sets display name for a property, event or public void method having zero (0)
arguments.
<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="100" Width="360" Title="Display name example">
<Window.Resources>
<wpfApplication:DisplayNameConverter x:Key="DisplayNameConverter"/>
</Window.Resources>
<StackPanel Margin="5">
<!-- Label (DisplayName attribute) -->
<Label Content="{Binding Employee, Converter={StaticResource DisplayNameConverter},
ConverterParameter=FirstName}" />
<!-- TextBox (FirstName property value) -->
<TextBox Text="{Binding Employee.FirstName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
namespace WpfApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Employee _employee = new Employee();
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
https://riptutorial.com/ 266
public Employee Employee
{
get { return _employee; }
set { _employee = value; }
}
}
}
namespace WpfApplication
{
public class DisplayNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo
culture)
{
// Get display name for given instance type and property name
var attribute = value.GetType()
.GetProperty(parameter.ToString())
.GetCustomAttributes(false)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
EditableAttribute sets whether users should be able to change the value of the class property.
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
https://riptutorial.com/ 267
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;
}
namespace WpfApplication
{
public class EditableConverter : IValueConverter
{
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();
https://riptutorial.com/ 268
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo
culture)
{
throw new NotImplementedException();
}
}
}
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.
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.
Example: RangeAttribute
The RangeAttribute gives the maximum and minimum value for a numeric field.
https://riptutorial.com/ 269
{
[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).
Method declaration:
if (input?.ToString()?.ToUpperInvariant() == "APPLE")
{
result = new ValidationResult("Apples are not allowed.");
}
return result;
}
}
Custom validation attributes can be created by deriving from the ValidationAttribute base class,
then overriding virtual methods as needed.
if (!string.IsNullOrEmpty(inputValue))
{
isValid = inputValue.ToUpperInvariant() != "BANANA";
}
return isValid;
}
https://riptutorial.com/ 270
}
Data annotations are a way of adding more contextual information to classes or members of a
class. There are three main categories of annotations:
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.
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
https://riptutorial.com/ 271
include various information such as the object to be validated, some properties, the name to
display in the error message, etc.
Once the context is created, there are multiple ways of doing validation.
And More
To learn more about manual validation see:
https://riptutorial.com/ 272
Chapter 45: DateTime Methods
Examples
DateTime.Add(TimeSpan)
DateTime.AddDays(Double)
DateTime.AddHours(Double)
DateTime.AddMilliseconds(Double)
https://riptutorial.com/ 273
date2 - date1, date2.Ticks - date1.Ticks);
if (result < 0)
relationship = "is earlier than";
else if (result == 0)
relationship = "is the same time as";
else relationship = "is later than";
DateTime.DaysInMonth(Int32,Int32)
// daysInFeb gets 28 because the year 1998 was not a leap year.
int daysInFeb = System.DateTime.DaysInMonth(1998, Feb);
Console.WriteLine(daysInFeb);
DateTime.AddYears(Int32)
Console.WriteLine();
https://riptutorial.com/ 274
Console.WriteLine("{0,2} year(s) from now: {1:d}",
ctr, baseDate.AddYears(ctr));
1. 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 .
2. 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:
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);
DateTime.Parse(String)
// Converts the string representation of a date and time to its DateTime equivalent
Console.WriteLine(dateTime.ToString());
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
https://riptutorial.com/ 275
DateTime dateTime;
Console.WriteLine(result);
}
You might want to use it when parsing DateTimes from different cultures (languages), following
example parses Dutch date.
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}
using System;
https://riptutorial.com/ 276
{
public static void Main()
{
var date = new DateTime(2016,12,31);
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);
DateTime Formating
DateTimeFormatInfo specifies a set of specifiers for simple date and time formating. Every
specifier correspond to a particular DateTimeFormatInfo format pattern.
//Create datetime
DateTime dt = new DateTime(2016,08,01,18,50,23,230);
https://riptutorial.com/ 277
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 = String.Format("{0:y yy yyy yyyy}", dt); // "16 16 2016 2016" year
var month = String.Format("{0:M MM MMM MMMM}", dt); // "8 08 Aug August" month
var day = String.Format("{0:d dd ddd dddd}", dt); // "1 01 Mon Monday" day
var hour = String.Format("{0:h hh H HH}", dt); // "6 06 18 18" hour 12/24
var minute = String.Format("{0:m mm}", dt); // "50 50" minute
var secound = String.Format("{0:s ss}", dt); // "23 23" second
var fraction = String.Format("{0:f ff fff ffff}", dt); // "2 23 230 2300" sec.fraction
var fraction2 = String.Format("{0:F FF FFF FFFF}", dt); // "2 23 23 23" without zeroes
var period = String.Format("{0:t tt}", dt); // "P PM" A.M. or P.M.
var zone = String.Format("{0:z zz zzz}", dt); // "+0 +00 +00:00" time zone
You can use also date separator / (slash) and time sepatator : (colon).
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.
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
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
https://riptutorial.com/ 278
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
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
DateTime.TryParseExact(String,String,IFormatProvider,DateTimeStyles,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
https://riptutorial.com/ 279
Use custom formats with M and MM.
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
https://riptutorial.com/ 280
{
Console.WriteLine("'{0}' is not in an acceptable format.", dateString);
}
Outputs
https://riptutorial.com/ 281
Chapter 46: Delegates
Remarks
Summary
A delegate type is a type representing a particular method signature. An instance of this type
refers to a particular method with a matching signature. Method parameters may have delegate
types, and so this one method to be passed a reference to another method, which may then be
invoked
Func represents methods with a return type matching TResult, and Action represents methods
without a return value (void). In both cases, the additional generic type parameters match, in
order, the method parameters.
Invoking delegates
Delegates can be invoked using the same syntax as methods: the name of the delegate instance,
followed by parentheses containing any parameters.
Assigning to delegates
Delegates can be assigned to in the following ways:
https://riptutorial.com/ 282
Combining delegates
Multiple delegate objects can be assigned to one delegate instance by using the + operator. The -
operator can be used to remove a component delegate from another delegate.
Examples
Underlying references of named method delegates
When assigning named methods to delegates, they will refer to the same underlying object if:
• They are the same instance method, on the same instance of a class
// ...
Console.WriteLine(instance1.Equals(instance2)); // False
Console.WriteLine(instance1.Equals(instance1Again)); // True
Console.WriteLine(@static.Equals(staticAgain)); // True
The following syntax creates a delegate type with name NumberInOutDelegate, representing a
method which takes an int and returns an int.
https://riptutorial.com/ 283
This can be used as follows:
The example delegate instance is executed in the same way as the Square method. A delegate
instance literally acts as a delegate for the caller: the caller invokes the delegate, and then the
delegate calls the target method. This indirection decouples the caller from the target method.
You can declare a generic delegate type, and in that case you may specify that the type is
covariant (out) or contravariant (in) in some of the type arguments. For example:
Like other generic types, generic delegate types can have constraints, such as where TFrom :
struct, IConvertible where TTo : new().
Avoid co- and contravariance for delegate types that are meant to be used for multicast delegates,
such as event handler types. This is because concatenation (+) can fail if the run-time type is
different from the compile-time type because of the variance. For example, avoid:
https://riptutorial.com/ 284
Also supported are delegates where some parameters are modified by ref or out, as in:
The System namespace contains Func<..., TResult> delegate types with between 0 and 15
generic parameters, returning type TResult.
The System namespace also contains Action<...> delegate types with different number of generic
parameters (from 0 to 16). It is similar to Func<T1, .., Tn>, but it always returns void.
Predicate<T> is also a form of Func but it will always return bool. A predicate is a way of specifying a
custom criteria. Depending on the value of the input and the logic defined within the predicate, it
will return either true or false. Predicate<T> therefore behaves in the same way as Func<T, bool>
and both can be initialized and used in the same way.
https://riptutorial.com/ 285
// Both of these return false
var predicateReturnsFalse = predicate("xyz");
var funcReturnsFalse = func("xyz");
The choice of whether to use Predicate<T> or Func<T, bool> is really a matter of opinion.
Predicate<T> is arguably more expressive of the author's intent, while Func<T, bool> is likely to be
familiar to a greater proportion of C# developers.
In addition to that, there are some cases where only one of the options is available, especially
when interacting with another API. For example List<T> and Array<T> generally take Predicate<T>
for their methods, while most LINQ extensions only accept Func<T, bool>.
Example.AddOne takes an int and returns an int, its signature matches the delegate Func<int,int>.
Example.AddOne can be directly assigned to addOne because they have matching signatures.
Delegate Equality
Console.WriteLine(action1.Equals(action1)) // True
Console.WriteLine(action1.Equals(action2)) // False
Console.WriteLine(action1Again.Equals(action1)) // True
These rules also apply when doing += or -= on a multicast delegate, for example when subscribing
and unsubscribing from events.
https://riptutorial.com/ 286
Note that the explicit declaration of type is required when creating a variable this way:
class FuncAsParameters
{
public void Run()
{
DoSomething(ErrorHandler1);
DoSomething(ErrorHandler2);
}
Addition + and subtraction - operations can be used to combine delegate instances. The delegate
contains a list of the assigned delegates.
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace DelegatesExample {
class MainClass {
https://riptutorial.com/ 287
private delegate void MyDelegate(int a);
// Output:
// 1
d1(1);
// Output:
// System.Int32
d2(1);
MyDelegate d3 = d1 + d2;
// Output:
// 1
// System.Int32
d3(1);
MyDelegate d4 = d3 - d2;
// Output:
// 1
d4(1);
// Output:
// True
Console.WriteLine(d1 == d4);
}
}
}
In this example d3 is a combination of d1 and d2 delegates, so when called the program outputs
both 1 and System.Int32 strings.
If a multicast delegate has a nonvoid return type, the caller receives the return value from the last
method to be invoked. The preceding methods are still called, but their return values are
discarded.
class Program
{
public delegate int Transformer(int x);
https://riptutorial.com/ 288
t += Cube;
Console.WriteLine(t(2)); // O/P 8
}
t(2) will call first Square and then Cube. The return value of Square is discarded and return value of
the last method i.e. Cube is retained.
Ever wanted to call a multicast delegate but you want the entire invokation list to be called even if
an exception occurs in any in the chain. Then you are in luck, I have created an extension method
that does just that, throwing an AggregateException only after execution of the entire list completes:
if(exceptions.Any())
{
throw new AggregateException(exceptions);
}
}
}
try
{
delegateInstance.SafeInvoke();
}
catch(AggregateException ex)
{
https://riptutorial.com/ 289
// Do any exception handling here
}
}
This outputs:
Target 2 executed
Target 1 executed
Closures are inline anonymous methods that have the ability to use Parent method variables and
other anonymous methods which are defined in the parent's scope.
In essence, a closure is a block of code which can be executed at a later time, but
which maintains the environment in which it was first created - i.e. it can still use the
local variables etc of the method which created it, even after that method has finished
executing. -- Jon Skeet
https://riptutorial.com/ 290
myObject.TestDate > DateTime.Now;
//or this:
if(DateIsValid(this)){
CallAnotherMethod();
}
}
}
In the spirit of clean coding, encapsulating checks and transformations like the one above as a
Func can make your code easier to read and understand. While the above example is very simple,
what if there were multiple DateTime properties each with their own differing validation rules and
we wanted to check different combinations? Simple, one-line Funcs that each have established
return logic can be both readable and reduce the apparent complexity of your code. Consider the
below Func calls and imagine how much more code would be cluttering up the method:
https://riptutorial.com/ 291
Chapter 47: Dependency Injection
Remarks
Wikipedia definition of dependency injection is:
**This site features an answer to the question How to explain Dependency Injection to a 5-
year old. The most highly rated answer, provided by John Munsch provides a surprisingly
accurate analogy targeted at the (imaginary) five-year-old inquisitor: When you go and get
things out of the refrigerator for yourself, you can cause problems. You might leave the
door open, you might get something Mommy or Daddy doesn’t want you to have. You
might even be looking for something we don’t even have or which has expired. What you
should be doing is stating a need, “I need something to drink with lunch,” and then we will
make sure you have something when you sit down to eat. What this means in terms of
object-oriented software development is this: collaborating classes (the five-year-olds)
should rely on the infrastructure (the parents) to provide
** This code uses MEF to dynamically load the dll and resolve the dependencies. ILogger
dependency is resolved by MEF and injectd into the user class. User class never receives
Concrete implementation of ILogger and it has no idea of what or which type of logger its using.**
Examples
Dependency injection using MEF
[Export(typeof(ILogger))]
[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
{
https://riptutorial.com/ 292
public void Log(string message)
{
//Write the message to file
}
}
[ImportMany]
private IEnumerable<Lazy<ILogger, ILoggerMetaData>> _loggers;