An open API service indexing awesome lists of open source software.

https://github.com/joehunterdev/c-sharp-masterclass

💻 📚 📝 Extensive c# notes for reference or study. Summarized and annotated by yours truly.
https://github.com/joehunterdev/c-sharp-masterclass

master-class udemy ultimate-guide

Last synced: 1 day ago
JSON representation

💻 📚 📝 Extensive c# notes for reference or study. Summarized and annotated by yours truly.

Awesome Lists containing this project

README

          

# C# Ultimate Guide Project Master Class 💻 📚 📝
Welcome to the c# master class notes. Nothing here but lovingly crafted notes for personal use. Summarized and formatted by yours truly. A highly recommended [C# Masterclass - Harsha Vardhan](https://www.udemy.com/course/c-sharp-oop-ultimate-guide-project-master-class/) for anyone interested in c#.

- What 🤔:
.net it is not a single language. It's an application dev platform to build desktop, web and mobile. Calculator, Supermarket app (may or may not integrate with web) standalone. Web apps live on a server and usually interact with a database. Mobile apps are installed on phones. It is a technology to develop applications. It's a free development platform since 2002. They will not execute directly on the operating system. It runs on a component called CLR. .net supports more than 30 languages. C#, VB, VC++ etc.

- Why 🤷‍♀️:
Secured execution environment 🔒
Wide variety of applications and languages 🌎
Code reusability 🔁

Modules and apps 📦:

**ASP.net** Websites (static collection of websites), Web Applications (dynamic web content), Web Services (Reusable programs on the web)
**C#.net** Windows GUI apps, Windows Services (no GUI components), Console Applications (CLI apps in command prompt window)

*These must be installed on the user machine* 💻

---

## 10 Common Language Infrastructure
c# application source is written by dev 🧑‍💻
Ultimately we need to convert to "Native Machine Code" 🖥️
Intermediate languages are (Language Neutral) 🌐
CLR is an execution language (Execution Engine of all .net modules) 🚀
Native Machine code is operating system-specific language (Executed by OS) 💻
**c# application source code** -> compiler -> **Intermediate language** -> **Common Language Runtime** -> **Native Machine Code**

In VS you can hit the start button to compile to IL. So for c#, we have a c# compiler
You can open the project in file explorer and check out an .exe
You can see the source of this by typing the command `ildasm` intermediate language disassembler located in /bin/debug

---

## Common Language Runtime
THis is the most important componenet in .net

CLR:
"Execution environment" for all .net languages.
Code execution env that executes all types of .net
Applications develoier in any .net language runes based on "CLR" only
CLR is part of .net framework pre-installed on windows

#### Components of CLR:
Class Loader, Exception Manager, Memory Manager, Garbage collector, JIT Compiler, Thread Manager, Security Manager

1. Class Loader
- Loading classes from compiled source code to memory
- Loads a class, when it is needed (before creating objec)
2. Memory Manager
- Allocating necessary memory for objects
- When an object is created in teh code, certain amount of memory will be allocated for the oject in applications "heap"
3. Garbage Collector
- Freeing (deleting) memory of objects
- Identifies all unreferenced objects adn delete them in memory (RAM)
4. JIT (Just In Time) compiler
- Convert the MSIL code into Native Machine Language
- Compiles the code of a class when it is needed (before executing that particular class)
5. Exception manager
- Raise notifications while run-rime errors
- Creates exception logs
6. Thread Manager
- Create threads (background process) to exectute the code
- Entire program is treated as "Main thread"
- Developer can create sub threads (child threads) to do background processes
7. Security manager
- Verifies whether the appliation has permision to access resource or not
- Before execturing the app it verifies whether the application has not attacked by malicius programs & has necessary permissins to access files / folders and hardware resources

---

## .net Framework Architecture

Is a combo of Common Language Runtime (Runtime engine) + Framework Class Library (OOP collection of classes used to develop apps)

Learning about availbable components can be found in the .net framework arhciteture.

CLS (Common Language Specification)

FCL is comprised of: Win forms, ASP.net, WPF, ADO.et, Base Class Library, Common Language Runtime

#### BCL (Base Class Library)

> Contains a set of predefined classes that can be used in all types of .net applications & langugages. for general I/O operations, type conversion, creation of threads etc.

Ex:
- Console
- String
- StringBuilder
- Convert
- Thread
- Task
- etc

#### ADO.net

> Contains a set of pre-defined classes that can be used in all types of .net applications & languages for connecting to databases, inserting, updating, deleting.

Ex:
- SqlConnection
- SqlCommand
- SqlDataAdapter
- SqlDataReader
- etc

#### Win Forms

> Contains a set of pre-defined classes taht can be used in windows gui applications for dev of gui elements such as form, textboc, button, checkbox etc

Ex:
- Form
- Label
- Button
- TextBox
- etc

#### WPF (Windows Presentation Foundation)

> Contains a set of prededifined classes that can be used in Ricch Windows GUI applications for dev of GUI elements. Such as window, textbox, button, checkbox, radio button

Ex:
- Window label
- Button
- Textbox
- etc

##### Asp (Active Server Pages)

> Contains a set of pre-defined calsses that can be used in Web Apps for dev of gui elements, such as page, textbox, button, checkbox, radio button etc

Ex:
- Page
- Label
- Button
- TextBox
- etc

#### CLS (Common Language Specification)

> Contains a set of rules (concepts) that are common to all .net languages such as c#.net, Vb.net etc. By following practical implementation you may not need to worry too much about this.

- Common rules of CLS:
- CTS (Common type system) : Contains datatypes such as Int32, Int64, Single, Double etc
- Classes & objects
- Reference Variables
- Method Parameters
- Generics

> These datatypes help fluid translation between .net languages

## Versions of .net

.net 4.6.1 core

SHA-2, Elliptic Curve Cryptography API
64 bit JIT compiler for managed code
Introduction of .NET Core
- (Multiplatoform support for windows, LINUX,Mac, Android, IOS)

---

## .net Core

> We can say .net has two flavors *.net framework* (only windows) and *.net core*

- Introduced in 2016
- Microsofts application dev platofrom t for any desktop, mobile and embedded (iot)
- Supports Various OS
- Versions 1.0 - 3.1
- Mainly used in Xamarin & ASP.net Core
- Open Source (via MIT licence)
- Contains the class library which is a subset of .NET Framework
- Doesnt contain any windows specific classes / run time services
- c# / vb.net can be used for writing code of .NET Core

---

## Visual Studio

Visual Studio 2015 supports .NET framework 4.6.1

Visual Studio 2022 supports (2021)
🔹 .NET framework 4.6.1 - 4.6
🔹 .NET Core 2.1, 3.1
🔹 .NET 5.0 - 6.0

---

## Introduction to c#

🔸 What: Developed in 2002 for COnsole Apps, WIndows GUI and Windows Services.

🔸 Features:
- OOP Langguage
- Case Sensitve
- Strongly Typed Lang
- Compiler based lang
- Compiled based on CLI, executed by CLR
- Developed by Anders Hejlsberg

---

## Introduction to Objec, Class, Fields & Methods ()

🔸 Objects:

- Things that exist in the real world (small unit) or entity

🔸 Classes:
> 2 types class based or prototype
- c# is a class based oop language
- A class is a model of objects
- class isnt a collection of objects

🔸 Methods:
- Are a collection of statements to perform certain operations
- Are not stored in the object but associated

---

## Introducing Namespaces

> Is a collections of classes, made for grouping: All classes for *student, lecturer, staff* may belong to a namespace called *university*

We can access like `namespace.class` or a more pracitcal example `university.student`

Namespaces are included on top usually

---

## Language Tokens

The list of words available in a language: Keywords, Operators, Literals (), Identifiers ()

🔸 Keywords: *always lower case*

🔸 Operators: *see language tokens*

🔸 Literals: Are *fixed values*: String, Bool( true or false) , integer etc. Requires no declaration

> **Character literals** should be in '' like `'a', '\''`
> **String literals** should be in ""

🔸 Identifiers: All types of names (variable names, class names, field names, property names, method names etc)

## Versions of c#

🔹 Latest versions are 9 / 10

🔹 5.0

- Async and Await

🔹 7.2
- private protected access modifier
- in parameter modifier

🔹 7.3
- ==

🔹 8.0:

- Readonly structs
- Switch expressions
- Using Declarations
- Static Local Functions

- Default interface methods.
- Nullable reference types.
- Pattern matching enhancements.
- Asynchronous streams / Asynchronous disposable.
- Using declarations.
- Enhancement of interpolated verbatim strings.
- Null-coalescing assignment.
- Static local functions.

---

## Naming Conventions

🔸 camelCase:
For all local variables and parameters

🔸 PascalCase:
For all class names, structure names, namespace names, field names, method names, property names.

🔸 IPascaleCase:
For all interface names

🔸 _camelCase:
For all private fields

---

## Installing Visual Studio 2022

For practice purposes:

🔸 **community** version will suffice
🔸 **Professional** requires a licence fee
🔸 **Enterprise** is for large businesses of < 100 employees

For this course we only need VS Community version with component

- *.NET desktop development* & *ASP.NET and web development may also be usefull*

Visit also individual components its a good idea to include all .NET runtime & .NET Framework dev tools, sdk etc so you can test further.

- *Select all up to .NET framework 4.8 targeting pack* (This is optional but usefull).

Its nice to also *pin to taskbar*

Before you can use you will need to *sign in* with a microsoft account

---

## Creating first C# App

Note the `Main` method inside a class
Main method should always be static void
`static` Static, in C#, is a keyword that can be used to declare a member of a type so that it is specific to that type. The static modifier can be used with a class, field, method, property, operator, event or constructor.
`void` means that the method doesnt return any value to the caller

~~~
class Sample {

static void Main()
{

System.Console.WriteLine("Hi im in console");
System.Console.ReadKey();

}

}
~~~

---

## System Console Class

`Namespace.Classname.Method`
System is a namepsace
It is a static class
Console class is Base Class Library
`writeLine` goes to next line automatically

`Clear` empties the console
`ReadLine` accepts a string from keyboard, always returns string, even numbers are treated as string

---

## Variables
*Vary Able*
Are a named memory location in ram.
All variables stored in stack
every method call a new Stack
variables value can be changed
The variables must be declared before usage
You cant change the type after execution

- Declaration `DataType VariableName;`
- with init `DataType VariableName = value` - - overwriting `VariableName = newvalue;` -
- getting value `VariableName`

You *cant redeclare variable that is reseved as keyword*

---

## Primitive Types

Basically Predifined types.
> A type specifies what type of value you want to store in memory. There are two two types: Primitive and non primitive.

🔸 Primitive: (byte, short, int, bool)
- Stictly a single value
- building blocks of none primitive types

🔸 Non-Primitive: (strings, classes)
- Stores one or more values
- Usually contains multiple members

- Sbyte = Small Byte is (0) by default
- Byte 8 bit *un-signed* int meaning it cant be negative

- Short is 16 bit and Ushort (again ushort is unsigned)

8 Bits is equal to 1 byte
- int is a large negative to positive number. you can get min value like *int.MinValue* | uint mostly same as int but unsigned meaining only positive

- long are 8 bytes of memory (very large datatype)

- float supports decimal types. default value is: `0F`
- double is a huuge floating point number default: `0D`
- decimal with a lot of decimal place can prefix with `0M` to define this datatype
- char supports all language characters. default:`\0` or null
- string (non prmitive) collection of unicode chars default value: null
- bool either (true/false) default: `false`

> You can access the default value of a type `default(int)`

## Operator

- Are a symbols to perform operation
- Recieve one or more operands (values) and returns one value

Classification:
- Arithmetical (+,-,*)
- Assignment (=, +=,*=)
- Increment/Decrement (n++,++n,n--)
- Comparison (==, !=,<,>)
- Logical (&,&&,|,||,!,^(Logical Exclusive))
- Concat ("string"+"string2")
- Ternary (?:,)

> Post incrementation n++ (first return value then increment)
Operators have a preference or order of evalutaion

## If, if-else, nested-if

Control statements are used to control the program execution flow.
Used to make the execution flow jump forward

Conditional:
- if(simple-if, if-else, else-if,nested-if)
- switch-case

Looping:
- while
- do-while
- for

Jumping:
- goto
- break

## Break
In C#, the break statement is used to terminate a loop(for, if, while, etc.) or a switch statement on a certain condition.

## Continue

In C#, the continue statement is used to skip over the execution part of the loop

## Go to

The C# goto statement is also known jump statement. It is used to transfer control to the other part of the program

Not safe to use without an end condition

---

# Object Oriented Programing

For small and large projects
Object is a single unit

## Undstanding OOP

~~~

class car {

string regNo;
string carModel

int calculcateEmi(int carPrice, int nuOfMonths,in interestRate){

}

}
~~~

## Classes & Objects

PascalCase for ClassNames

## AccessModifiers:

- Fields,
- Methods,
- Constructors,
- Properties,
- Events, (raise notification to other classes)
- Deconstructors (clear unmanaged resources)

Can be:
- Internal (accesible within same assembly)
- Public (accesible in same and other assembly) ie: Internal class

Compiled source of a project is called an assembly (.exe) in form of Intermediate language

By default accessors are Internal

## Modifier:

- Static (belongs to the type itself rather than to a specific object)
- Abstract (the thing being modified has a missing or incomplete implementation)
- Sealed (cant be inherited)
- Partial (multiple partial classes that have same name are combined)

*These are all optional*

- Add Class: In vs *solution->add a new project* and select class library.net framework. *we can now access inside the class library from console app*

- Reference: We can to add a reference to our second class. By going to our top class and selecting **add->reference projects and select your library**

You can see on the right hand side all the main classes references.

> Second class is not as accessible so we can set this to `internal`

The **stack** references variables from the heap
Objects are stored in the **heap** which is a grouping of all initialized objects

Since the object is nameless we need to create a reference.

### 1. Creating Reference Variable

`ClassName referenceVariable;`

~~~

class Sample {

static void Main(){

Customer c; //referenceVariable

}

}
~~~

Default values of references are null

### 2. Creating Object and Store its Reference into the Reference Variable

`new Classname()`

~~~

class Sample {

static void Main(){

//referenceVariables: (all local by default)
Customer c1, c2;

//Objects: Contain whatever properties we have defined in Customer
new c1 = Customer(); //All these objects get stored in the heap only
new c2 = Customer(); //2nd object
// Note these new objects are nameless. For this we need the reference variable

}

}
~~~

## Important Features Points to remember about Objects
- Object is representaiton of a thing
- All objects created based on classes
- Foreach app exec a new heap will be created
- All reference variables (local variables of methods) are stored in the stack
- Foreach mehtod call a new will stack will be created
- Method is collection of statements to perform functions
- Single values should be stored as field
- Class supports internal / public modifiers
- Class supports 4 modifiers: static, abstract, sealed and partial
- Object stores actual data (group of fields) and can access methods of a class
- A reference variable stores address for example (just one object)

---

## When to use Static (additional info)

### Methods:
- Good for operations that *don't require any data from an instance* of the class (from this ) and can perform their intended purpose solely using their arguments

### Fields:
- To *keep a count* of the number of objects that have been instantiated
- To *store a value that must be shared* among all instances

### Classes
- To use as a *unit of organization* for methods *not associated with particular objects* like `static void Main()`

---

# Fields

## Understanding Fields

Is a variable stored inside an object
Isolated for each object

Field Creation Syntax:
- `accessModifier modifier type Fieldname`
- `public int proudctID`

Static:
Const:
Readonly:

A good practice is to define all re-useable classes inside the class library

## Access Modifiers

Aka Access Specifier or Visibility Modifier.

### A child class in c#:
~~~

public class DomesticProduct:Product{

}

~~~
## Static Fields

Are stored outside the object
Accessible through classname (not object)
Example: `Math.Round()`
Are common to all objects ie:

~~~

class BankAccount {

//instance fields
long accountNumber;
string accountHolderName;
double currentBalance;

static string bankName; // Note this will not be stored in the heap
}

~~~

### Class Memory In Heap
bankName = "Bank Of Joe";

### Objects in Heap

1.

accountNumber:1001
accountHolderName:"Bill"
currentBalance: 4000

2.
accountNumber:1002
accountHolderName:"Steve"
currentBalance: 5001

### 🏭 Classes
- To use as a *unit of organization* for methods *not associated with particular objects* like `static void Main()`

---

# 🌳 Fields

## Understanding Fields

🔢 Is a variable stored inside an object
🔢 Isolated for each object

Field Creation Syntax:
- `accessModifier modifier type Fieldname`
- `public int proudctID`

🖼️ Static:
🔒 Const:
🔒 Readonly:

A good practice is to define all re-useable classes inside the class library

## Access Modifiers
👀 Aka Access Specifier or Visibility Modifier.

### A child class in c#:
~~~

public class DomesticProduct:Product{

}

~~~
## Static Fields

🔒 Are stored outside the object
🔑 Accessible through classname (not object)
Example: `Math.Round()`
Are common to all objects ie:

~~~

class BankAccount {

//instance fields
long accountNumber;
string accountHolderName;
double currentBalance;

static string bankName; // Note this will not be stored in the heap
}

~~~

### Class Memory In Heap
bankName = "Bank Of Joe";

### Objects in Heap

1.

accountNumber:1001
accountHolderName:"Bill"
currentBalance: 4000

2.
accountNumber:1002
accountHolderName:"Steve"
currentBalance: 5001

## Constants

> Like static they are common to all objects of the class
We cant change constant valuess

- Accessible with the class name `Product.CategoryName`
- They are not stored in the object
- Constant fields are replaced directly with the value (on compilation) not stored in memory
- They must be initialized, in line with declaration (literal value only) `public const string CategoryName ="Electronics"`
- Can be decared as `local` constants in a method
- They cannot be referenced variables

Written like so:
`AccessModifier const type FieldName= value`
`private const int CategoryName=Electronics`

> Good if: If you dont require to change this field

---

## Readonly

🔢 Readonly fields are like instance fields, thate is stored in every object individually We cant chagne the value of readonly

- Readonly are accessible with reference variable (via object)
- Must be initialized either *in-line with declaration* or *in the constructor*

Written like so:
`AccessModifier readonly DataType FieldName= value`
`private readonly int dateOfPurchase=1804291`

> Good if: If we have some data thats *isolated to every object*. At same time we *dont want this value to be changed*.

## Local Constants

Access modifier is not applicable `const string developerName="joey"`

## Keypoints about fields
## 🌟 Fields
Fields are variables that are declared in the class but stored in object.

Access modifiers: private, protected, internal, etc.

Modifiers of fields: static, const, readonly.

Instance fields: Individual for each object; Static fields are common (one-time) for all objects.

Constants: Must be initialized along with declaration; **Readonly** must be initialized either 'along with declaration' or in 'instance constructor'.

---
## 🚀 Code Source Examples
(Fields Example Program.cs (ConsoleApp))[_cs\FieldExample\Program.cs]
(Fields Example Product)[_cs\FieldExample\Class1.cs]

## 📝 Task Working with Multiple Objects
Create a console application that stores and displays 10 employees information of Harsha Inc.

Class Library: Contains Employee class. Console Application: Consumes the Employee class and creates 10 objects of Employee class.

[x] Step 1: Create a class library and console application. Add reference of class library into console application.

[x] Step 2: Create a class called Employee in the class library with fields EmpID, EmpName, SalaryPerHour, NoOfWorkingHours and NetSalary. Additionally, add the following fields:

- A static field called OrganizationName and initialize it as "Harsha Inc." in Main method.

- A constant field called TypeOfEmployee and initialize it as "Contract Based" along with declaration.

- A readonly field called DepartmentName and initialize it as "Finance Department" in constructor.

[x] Step 3: Create up to 10 objects of Employee class in the console application. Read each employee details (EmpID, EmpName, SalaryPerHour, NoOfWorkingHours) from the user (from the keyboard) using loop.

Calculate net salary (SalaryPerHour * NoOfWorkingHours).

And display the all details of the same object (including EmpID, EmpName, SalaryPerHour, NoOfWorkingHours, NetSalary, OrganizationName, TypeOfEmployee, DepartmentName) and then ask the user 'Do you want to continue to next employee'.

If the user choose 'Yes', proceed to the next employee; otherwise stop the loop.

//studying Collections, it will pay off in the long run.

# 🎛️ Methods

The void keword is usefull when the method does not need to return anything.

methods use `PascalCase`

## 🔒 Encapsulation

Concept of grouping data together. Keeps safe from interference.

- Fields: store data (have long lives)
- Methods manipulate data
- class is used to group these together

We can pass parameters to methods

Getters and setters demonstrate this principle

~~~
public void SetQuantityInStock(int value)
{
quantityInStock = value;
}

public double GetQuantityInStock()
{
return quantityInStock;
}
~~~
---
## 🔒 Abstraction

Where the class can hide data/operations from outside of the class. Like internal methods.

So classes can be divided into two different types:

Private Fields / Methods
Public Fields / Methods

## 📝 Local variables & parameters

Parameters are stored in the stack. And created there on each method call.

Local Variables are those stored inside the method body. Short lives.

## 🤖 this keyword

Refers to the *current object* of a particular method.

Only available within the *instance methods*.

So **this** refers to the object in question.

> Good If: you have a parameter that is the same as a field you have to reference using **this**.

---

## 🚀 Static Methods

- Can be called directly on class.

- Called using **static** keyword.

- Can't access instance methods.

- Can't use **this** keyword.

### 🚀 Static Methods

> Good if: you want to handle static the fields.

~~~
Product.GetTotalNumberOfProducts();
~~~
~~~
public static int TotalNoProducts;

public static void SetTotalNumberOfProducts(int value)
{
TotalNoProducts = value;
}

~~~

## 📝 Reference Varibles as arguments

Imagine we have three objects created. We can pass these objects as references in the form of an argument.

- You can pass reference variables as an argument.
- The *data type* will be the class name.

~~~

int totalQuantity = Product.GetTotalQuantity(product1,product2,product3);

~~~

~~~~

//static method. Passing object references as arguments
public static int GetTotalQuantity(Product product1,Product product2,Product product3)
{
int total;
total = product1.GetQuantityInStock() + product2.GetQuantityInStock() + product3.GetQuantityInStock();

return total;

}

~~~~

---

## 📝 Default arguments

You can omit parameter values and a default will be taken.

~~~
public void SomeMethod(int a, int b = 0)
{
//some code
}

~~~

## 📝 Named arguments
Supply value to the parameter based on a name.

Good if: You want to change the order of parameters. Parameters are also understandable for other developers.

Like so: `MethodName(Param:value,Param2:Value2)`

---

## 📝 Method Overloading
Writing multiple methods with the same name in the class with different parameters.

Good If: You need one method to have several options while calling.

Rule: The param types of all the methods must be different.

~~~
void display() { ... }
void display(int a) { ... }
float display(double a) { ... }
float display(int a, float b) { ... }

// or

public void CalculateIva(double cost,double percentage){

//create local variable
double t;

if (cost <= 2000)
{
t = cost * 21 / 1000;

}
else
{
t = percentage * 10 / 1000;
}

//Finally store
iva = t;

}

~~~

## 📝 Parameter Modifiers - Default
Specify how the parameter receives a value.

~~~
double p = 7,4;
product2=CalculateTax(p);
~~~

Parameter Modifiers(List) :

- Default
- ref
- out
- in
- params

---

## 📝 Parameter Modifiers - Ref

How:
- The argument *will be assigned* into the parameter and vice versa. (Does both)
- The argument *must be a variable*.
- You cannot pass literal values.

~~~
double p = 7.2;
product1.Calculate(percentage:ref p)

double q = 10;
product2.CalculateTax(ref q)
~~~

~~~
public void CalculateIva(ref double percentage){}
~~~

## 📝 Out Parameters

This out parameter will be automatically assigned at the end.

How:
- The argument *will not be assigned* into the parameter. But only in reverse.
- The argument must be a variable (can be uninitialized).

~~~
double p = 200.500;
product1.CalculateIva(out p);
~~~
~~~
public void CalculateIva(out double percentage){

//create local variable
double t;
percentage = 10.45;
if (cost <= 2000)
{
t = cost * 21 / 1000;

}
else
{
t = percentage * 10 / 1000;
}

//Finally store
iva = t;

}
~~~
---
## 📝 Parameter modifier
Like normal the argument *will be assigned* into the parameter, but the parameter becomes *readonly*.
Meaning you cannot modify the value of the parameter.

~~~

double p = 9.2;
product1.CalculateIva(in p);
~~~
~~~
public void CalculateIva(in double percentage){

//create local variable
double t;
// percentage = 10.45; // This will get an error as the local variable cannot be changed (read only)

if (cost <= 2000)
{
t = cost * 21 / 1000;

}
else
{
t = percentage * 10 / 1000;
}

//Finally store
iva = t;

}
~~~

---

## 📝 Ref returns
This is when the reference of return variable will be assigned to receiving variable.

~~~
class Student
{
//public field
public int grade = 2;

//public method
public void PrintGrade()
{
System.Console.WriteLine("Grade: " + grade);
}

//public method with ref return
public ref int DoWork()
{
//return reference of 'grade' field
return ref grade;
}
}

class Program
{
static void Main()
{
//creating object of Student
Student s = new Student();

//call PrintGrade
s.PrintGrade();

//call DoWork
ref int g = ref s.DoWork();

//update the value of 'ref return'
g = 5;

//call PrintGrade after updating the value of 'ref return'
s.PrintGrade(); //Output: 5

System.Console.ReadKey();
}
}
~~~
---

## 📝 Parameter modifiers - params

How:
- All the set of arguments will be received as an array.
- The params parameter modifier can be used only for the last parameter of the method; and can be used only once for one method.

Good if: you don't know the number of the parameters you are going to receive.

~~~
class Student
{
public void DisplaySubjects(params string[] subjects)
{
System.Console.WriteLine(subjects[1]);
}
}

class Program
{

static void Main()
{
Student s = new Student();
s.DisplaySubjects("Theory of Computation", "Computer Networks", "Something Else");
}

}
~~~
---
## 📝 Local Functions

These are small local functions inside a method.

~~~
class Student
{
//method
public void DisplayMarks(int marks1, int marks2, int marks3)
{
double avgMarks = getAverageMarks();
System.Console.WriteLine("Marks 1: " + marks1);
System.Console.WriteLine("Marks 2: " + marks2);
System.Console.WriteLine("Marks 3: " + marks3);
System.Console.WriteLine("Average marks: " + avgMarks);

//create local function
double getAverageMarks()
{
//create local variable of local function
double avg;
avg = (double)(marks1 + marks2 + marks3) / 3;
return avg;
}
}
}
~~~

## 📝 Static Local Functions
Same as *Local* functions, except these cannot access local variables or parameters of containing method.

- This is to avoid accidental access of local variables or parameters.

~~~
public void DisplayMarks(int marks1, int marks2, int marks3)
{
double avgMarks = getAverageMarks(marks1,marks2,marks3);
System.Console.WriteLine("Marks 1: " + marks1);
System.Console.WriteLine("Marks 2: " + marks2);
System.Console.WriteLine("Marks 3: " + marks3);
System.Console.WriteLine("Average marks: " + avgMarks);

//create local function
static double getAverageMarks(int m1, int m2, int m3)
{
//create local variable of local function
double avg;
avg = (double)(m1 + m2 + m3) / 3;
return avg;
}
}
~~~

> Note you can change the c# language version inside the config using `8.0`
---

## 📝 Recursion
Is a method that calls itself.
Useful in mathematical computations such as finding a factorial number.

~~~
public double Factorial(int number)
{

if(number == 0)
{
return 1;
} else
{
return number * Factorial(number - 1);
}

}
~~~
---
# Type Conversion

## Implicit Casting

The lower numerical type can be automatically (implicitly) be converted into higher numerical type.

Implicit: `sbyte a = 10, int b; b=a;` or `char a = 'A', int b; b=a; // b = 5`
Note: double, decimal, bool and string cannot be converted implicitly

---
## Explicit Casting

We manually convert from one data type to another by specifying a data type within brackets.

> *Loosey Conversion* if destination type is not sufficient enough to store the converted value the value may loose.

Syntax:
`(DestinationDataType)SourceValue or (double)somenumber`
When:
- This is can be used at all times
- Child Class to Parent Class

---

## Parse
The string value can be converted to any numerical data type by using the "Parsing" technique. String->int

- The source must contain digits only; no spaces, alphabets or special characters.
- If the source is invalid it raises a format exception
Syntax:
- `DestinationDataType.Parse(SourceValue)`

## Try Parse

IF your not sure about your characters its recomended to use Try parse.

---
# Constructors

## Instance Constructors

These are special methods of a class which contain initialization logic of fields
Constuctor initializes fields and also contains the additional logic.

~~~
Employee emp1 = new Employee(101, "Scott", "Manager");
~~~
~~~
//fields
public int empID;
public string empName;
public string job;

//constructor
public Employee(int empID, string empName, string job)
{
this.empID = empID;
this.empName = empName;
this.job = job;
}
~~~

- Constructor name should be same as classname.
- Is private by default
- Can and cannot have params
- ***static*** is the only available modifier to a constructor
- recommended to be **public** or **internal**
- If it is a **private** it can only be called within the same class.
- *Can have* one or more params
- *Cannot* return a value; no return type. Is treated as void
- A single class can have on or more constructors. But all constrcutors mush have different params
- Can contain any init logic to be executed everytime
---

## Static Constructor

Created using **static** modifier
- Initializes static fields
- Executes only once ie when first object is created for the class or when the class is accessed for the first time in main method
- Is **public** by default
- access modifier cannot be changed
- Can contain init logic htat should be executed only once when a new object is created
- When we access the class for the first time the static constructor is initialized automatically `Employee emp1 `

~~~
System.Console.WriteLine("Company Name: ");
System.Console.WriteLine(Employee.companyName);
~~~
~~~
public static string companyName;

static Employee(){

companyName = "Joey Industries" // note were missing this

}
~~~

## Types of constructor
Provided by compiler or developer

There are two types of constructor: *Parameterized* and *Parameter less* (fixed values)

**Implicit (after compilation)**:
- Automatically provided constructor on compiliation. Which inits nothing. Also called the default constructor
- done only to satisfy the rule that *class should always have constructor*

**Explicit (while coding)**:
- Created manually by developer
- In the case that c# compiler downst provide a default constructor

---

## Constructor Overloading

Defining multiple constructors within same class

This is when we have mulitple constructors wiht same name in class with different parameters. (like method overloading)

- Its recommended to use parameter-less constructor in the class in the case of overloading

~~~
Employee emp1 = new Employee(); //num of params points to constructor 3
emp1.empID = 101; // this value will be 1

~~~

~~~
//constructor 1
public Employee(int empID, string empName, string job)
{
this.empID = empID;
this.empName = empName;
this.job = job;
}
//constructor 2
public Employee(int empID, string empName)
{
this.empID = empID;
this.empName = empName;
}
// constructor 3
public Employee() {

empID = 1 ;

}
~~~

---

## Object Initializer
Initialize field of an object without constructor.

Special syntax to initialize fields/properties of class along with creating object.

- executes after constructor
- it is only for init of fields/properties creating object(it cant have any init logic)

Exec Sequence: new Class() -> Constructor -> Object Initializer

Good if: You cannot find the matching constructor. And you want to initialize a specific bunch of fields

Eg: `Employee emp4 = New Employee() {empName ="Bob", job ="Exectutive"}`

---

## Key points

- *Instance constructor* initializes *instance fields* but *can also access static fields*
- Static constructor *inits only* static fields cant access instance fields
- Empty constructors are provided by default
- Recommended to write your paramter-less constructor first (if you are creating a parameterized constructor later)
- Use **object initializer** if you want ot initialize desired fields of an object, as soon as new object created.

---

# 9 Properties & Indexers

## Creating Properties

A property receives incoming value; validates the value; assigns value into a field.
A property can be a collection of two accessors: **get-accessor** and **set-accessor**

Set Accessor: `set {field = value} `
- a value its important to *Validate* before initialization
- has a default (implicit) parameter called value assigned
- Cant have any additional params
- Cant return a value

Get Accessor: `get {return field} `
- You can calculate a value an return the same (or) return the value of the field as is.
- Executes automatically when the property is retrieved
- Has no implicit parameters
- Cant have parameters
- Should return any value

### Features & Advantages of properties:

- Properties create a protection layer around fields. Also do some calculation automatically when someone has invoked the properyy
- no memory will be allocated for the property
- access mods is applicable for the property, set accessor & get accessor individually
- access modifiers if accessors must be more restrictive than the access modifier property

> Private fields should be prefixed with an _ `private int _empID`;

### Instance of a property

In console app we use intialization/assignment as usual
~~~
Employee emp1 = new Employee();
emp1.EmpID = 101;
Console.WriteLine(emp1.EmpID);// Outputs 101
~~~
~~~
public int EmpID{ // Note the use of PascaleCase on the property
set {
if(value >=100){ // with validation
_empID = value;
}
}

get { return _empID;}
}
~~~

> When creating field instances it is good practice to create them as *private* (if not required to access directly outside of class)

> When using the constructor remember we are not triggering the properties in this case. And the property validations *will not be executed*

> Overall its best to create properties for all fields as this is the best place to validate them.

### Static Properties

~~~
private static string _companyName;
public static string CompanyName{
set {

if(value.Length <=20){ // with validation
_companyName = value;
}

}
get { return _companyName;}
}
~~~

---

## Readonly & WriteOnly Properties

### Readonly
- are properties with only a **get** accessor
- reads and returns with no modifications

> optionally you can initialize the value of the read only field into the constructor
> If you try and write to this property you will get a *cannot be assigned - its read only* error

### Writeonly
- are properties with only a **set** accessor
- Validate and assign incoming value into field, but return the value

> The only way to access this is to *create a method* to be able to return this value

## Auto-Properties with Accessor Accessibility

- These are properties with no definition for set-accessor and get-accessor.
- Used to create property easily (with shorter syntax)
- Creates private field (with name as _propertyName) automatically at compilation time
- Auto-implemented property can be **write only** property or **read-only**

> Good if: You dont want to write any validation or calculation logic

~~~
Employee.emp1 = new Employee();
emp1.NativePlace = "New Delhi";
~~~
~~~
//automatic property
public string NativePlace{
internal get; // with access modifier will only be accesible within class employee assembly
set;
}
~~~

> You can mix auto implemented and manually implemented in your code there is no issue

---

## Auto-Implemented Property Initializers
Initializing default value into auto-implemented properties
New feature of c# 6.0

~~~
//automatic property with auto implementiation
public string NativePlace{get;set;}= "New York"; //Has been auto-initialized but can still be overwritten should you wish
~~~

## KeyPoints about properties
- Its recommended to always use
- you can use autoimplementation if it makes things easier
- Dont occupy any memory
- They provide a protection layer
- Can use readonly and writeonly
- Cant have additional parameters

---

## Indexer

Recieves a number / string. Search for the particular item among a group of items; set or get value into groups

It provides a shorter syntax to access a group of items.

It is a special member of class, which contains set-accessor and get-accessor to access a group of items / elements.

~~~
Car c = new Car();
Console.WriteLine(c[1]); // get a value

c[2] = "Jaguar"; //set or overwriting a value in indexer
Console.WriteLine(c[2]);
~~~
~~~
//private
private string[] _brands = new string[] { "BMW", "Skoda", "Honda" };

//public indexer
public string this[int index]
{
set
{
this._brands[index] = value;
}
get
{
return _brands[index];
}
}
~~~

📝📝📝
### Key Points:
- Indexers are always created with **this** keyword
- Are generally used to access a group of elements (items)
- *Parameterized properties* are called indexers
- Indexer must have one or more params
- *ref* and *out* parameter modifiers are not allowed
- Indexers cant be static
- Indexer is identified by its signature (where as property is its name)
- Indexer cant be static
- Indexer can be overloaded

## Indexer Overloading
This makes our indexer accessible via int and string parameters
~~~
//overloading
Console.WriteLine(c["first"]);
~~~
~~~
//indexer overloading
public string this[string name]
{

set
{
this._brands[Array.IndexOf(_names,name)] = value; // note we are retrieving from brands
}
get
{
return _brands[Array.IndexOf(_names,name)];
}
}

~~~
---

# Inheritance, Hiding & Overidding 🧬👻🔙

## Inheritance
- Concept of extending the parent class by creating a child class
- Allows classes to be arranged in hierarchy is a type of relationship
- The parent class acts as a "base type" of one or mpre child classes
child classes are derived from parents

Child class contains parent + childs members/fields

Syntax: `class Manager:Employee`

## Types of inheritance

**Single**:
ParentClass->ChildClass
One Parent, One Child Class
**Multiple**:
ParentClass->ChildClass1->ChildClass2
Multiple Parent Classes, One Child Class

~~~
interface Teacher
{
}

interface Physician
{
}

class MedicalTeacher : Teacher, Physician // To have two parents like this we need to use interface
{
}
~~~

**Multi-level**:
One Parent Class, One Child Class; and the Child class ahas another child class

**Hierachical**:
One Parent, Multiple Child Classes

**Hybrid**:
Hierachical Inheritance + Multilevel Inheritance

## Base Keyword
Accessing parent class's members in child class
- Optional
- base keyword represents parents clases members in the child class
- It is must to use when there is ambiguity
~~~
//method
public string GetFullDepartmentName()
{
return DepartmentName + " at " + base._location;
}
~~~

- accesible fields from parent class
- protected field of a parent class can only be accessible via the child class method

---

## Parent Class Constructor
Calling the constructor of parent class from child class

- Parent constuctor is called first
- Child constructor only initializes its own constructor
- Its **Optional** to call parent classes parameter less constructor from child
- It is a **Must** to call Parents classes parameterized constructor from the child class and pass arguments

~~~

Employee emp1 = new Employee(101, "Scott", "Hyderabad");
Manager mgr1 = new Manager(102, "Allen", "New York", "Accounting");

~~~
~~~
public class Employee
{
//constructor of parent class
public Employee(int empId, string empName, string location)
{
this._empID = empId;
this._empName = empName;
this._location = location;
}
}
~~~
~~~
public class Manager : Employee{

//constructor of child class
public Manager(int empID, string empName, string location, string departmentName) : base(empID, empName, location)
{
_departmentName = departmentName;
}
}

~~~
- Note use of **base()** that inits the parent constructor. &
- we are just passing same parameters (mpID, empName, location) to the base constructor
- base constructor gets executed before the body of the child constructor
- dont initialize the parent class fields in the child class constructor
---
## Method Hiding 🕵️‍♂️
Hiding/overwriting parent class's method using **new** keyword
Uses same name and parameters
- **new** keyword is optional but encourged
- Only done in child class

~~~
public class Employee
{

public GetHealthInsuranceAmount()
{
return "Amount is: 1500"
}
}

~~~
~~~
public class Manager : Employee{

//method hiding
public new GetHealthInsuranceAmount()
{
return "Amount is: 1500"
}
}
~~~

---
## Method Overiding 🔄
Using **virtual** keyword at parent class's method; **override** keyword in the child class's method

- Extending a parent classes method in the child class with the same name and params
- In child class you must use invoke parent method by using **base** keyword: `base.MethodName()`
- When overriding is done, if the method is called using child class object; the parents class method first executed followed by the child
- without virtual keyword in the parent class method the child cannot be overwritten
> This is differnt to hiding as **BOTH** methods will exectute
~~~
class Program
{
//Method overwriting
System.Console.WriteLine(mgr1.GetHealthInsuranceAmount()); //Employee.GetHealthInsuranceAmount and Manager.GetHealthInsuranceAmount
}
~~~
~~~
public class Employee
{
//virtual method
public virtual string GetHealthInsuranceAmount()
{
return "Health Insurance amount is: " + 500;
}

}

~~~
~~~
public class Manager : Employee{

//method overriding
public override string GetHealthInsuranceAmount()
{
System.Console.WriteLine(base.GetHealthInsuranceAmount());
return "Health Insurance amount is: " + 1000;
}

}
~~~
> Usefull when you want to use the original method and in addtion supply your own. Also when working with framworks such as WPF where we extend parent classes.

---

## Sealed Classes 🔒
A sealed class is a class that can be instantiated but not inherited
- Use this class whenever you dont want to let other developers to create child classes. *Prevent Inheritance.*

~~~
sealed public class Manager : Employee{

}

public class BranchManager : Manager{
// This will not work!
}

~~~

---

## Sealed Methods 🔒
Sealed methods must be "override methods"; which can't be overidden in the corresponding child class. The oposite of virtual method. `sealed override`

- Good If: You want to *prevent overriding* that particular method in the corresponding child classes.

~~~
public class Manager : Employee {

public sealed override string GetHealthInsuranceAmount()
{
System.Console.WriteLine(base.GetHealthInsuranceAmount());
return "Additional Health Insurance premium amount is: 1000";
}

}
~~~
---

# Abstract Classes & Interfaces 🤝

## Abstract Classes

A parent class for which *we can't create an object* but *can create child classes*

What:
- Provides common set of fields and methods to all of its child classes of a group
- can contain all types of members
- Has to be initialized through child

Good if: You want to create a class for which you feel creating an object is not meaningfull

~~~
public abstract class Employee{

}
~~~
---

## Abstract Methods
Abstract methods are declared in the parent class, with **abstract** keyword; implemented in child classes with **override** keyword

Good if: When you dont want the parent method to provide a definitiion of the method.

- Child class must implement body of the parent class
- can contain *method declaration* only but not method body
- child class must provide method body for abstract method

~~~
//parent class & abstract class
public abstract class Employee
{
//abstract method
public abstract string GetHealthInsuranceAmount(); //No method body
}
~~~

Use **virtual** method when the parent class method wants to provide the body. (It is optional to override in the child) Else use **abstract**.

> Remember it is compulsary to override the absract methods

~~~

System.Console.WriteLine(salesMan1.GetHealthInsuranceAmount()); //SalesMan.GetHealthInsuranceAmount //Output 500

~~~
~~~
//parent class & abstract class
public abstract class Employee
{
//method overridding the abstract methods
public override string GetHealthInsuranceAmount(){
//Method body
}
}
~~~
~~~
//child class
public class SalesMan : Employee
{
//method overriding the abstract methods
public override string GetHealthInsuranceAmount() // Notice again all isthe same apart from the body
{
return "Additional Health Insurance premium amount is: 500";
}
}
~~~
In all abstract classes are as easy as:
1. Create method in parent class without method body
2. Create method body in child class with same name, parameters,same type and access modifiers
3. Call the method through child class object
---

## Creating Interfaces 🤝
Think of an interface as set of just *abstract methods*, that must be implemented in child class. Defualt implementation

Example:
interface IVehicle: (*doesnt provide any method definition* only method names, signatures and parameters)
- Car - Bus (Share common methods)

- Generally interface names start with a **I**
- Default of all access modifeier in interface is public and abstract
- Cannot change the access modifier of interface methods
- When implementing interface the child promisises to *use all methods* of the parent class
- The method bodys are allowed to be different in each child class
- Cannot create object of interface
- Can create reference variable
- Can have mutliple interfaces in the same child class

Good if: You want to imply to another developer to follow a bunch of methods

~~~
//interface
public interface IEmployee
{
//abstract methods
string GetHealthInsuranceAmount();

//auto-properties
int EmpID { set; get; }
string EmpName { set; get; }
string Location { set; get; }
}
~~~
Good practice to rename the class and file

~~~
//child class
public class Manager: IEmployee
{
//field
private string _departmentName;
private int _empID;
private string _empName;
private string _location;

//properties
public int EmpID
{
set
{
if (value >= 1000 && value <= 2000)
{
_empID = value;
}
}
get
{
return _empID;
}
}

public string EmpName
{
set
{
_empName = value;
}
get
{
return _empName;
}
}

public string Location
{
set
{
_location = value;
}
get
{
return _location;
}
}


//method implementation of the interface methods
public string GetHealthInsuranceAmount()
{
return "Additional Health Insurance premium amount is: 1000";
}
}

~~~

### Abstract 🤝
Good if: When you have a mix of methods where you want to define a method body and not, use abstract classes.

### Interfaces 🤝

Good if: Whenever the in the parent you only want to provide abstract methods but dont want to provide any non abstract methods or other fields or constructors..

---

## Dynamic Polymorphism with Interfaces 🎭
Provides the ability for the developer to define different implements for the same method in the same class or different classes.

Polymorphism:
- Compile time (aka early binding / static)
- Run-Time (Late Binding)

~~~
// compile time - method overloading
public void Add(int a, int b);
public void Add(int a, int b, int c);
~~~

~~~
// runtime - method overloading
abstract class ParentClass{
public abstract void Add(int a, int b);
}
class ChildClass1: ParentClass{
public override void Add(int a, int b);
}
class ChildClass2: ParentClass{
public override void Add(int a, int b);
}

ParentClass c1;
c1 = new ChildClass1();
c1.Add(10,20);// calls ChildClass1.add

c1 = new ChildClass2(); // reference of previous object will be deleted
c1.Add(10,20);// calls ChildClass2.add

~~~

~~~
// runtime - with interfaces
interface InterfaceName{

void add(int a, int b);

}

class ChildClass1:InterfaceName{

public void Add(int a, int b);

}

class ChildClass2:InterfaceName{

public void Add(int a, int b);

}

InterfaceName c1;
c1 = new ChildClass1(); // c1 is interface reference variable
c1.Add(10,20);// calls ChildClass1.add

c1 = new ChildClass2(); // reference of previous object will be deleted
c1.Add(10,20);// calls ChildClass2.add

~~~
> note the same method has different implementations (polymorphism) this allows for differetn developers to pick and choose different implementations at runtime
---

## Mutliple Inheritance with interfaces 🤝
Creating child classes with multiple parent interfaces

In c# *multiple inheritance* is only possible using interfaces, that means a child class can have multiple parent interfaces

Keypoints:
- *One child - Multiple Parent Classes / Parent Interfaces* is called *Multiple inheritance*
- The child *Must* Implement all methods of all the interfaces, that its inherited from

~~~
// Multiple Inheritance
interface Interface1{
void Method1(param1,param2,..);
}
interface Interface2{
void Method2(param1,param2,..);
}
class ChildClass: Interface1,Interface2{
public void Method1(param1,param2,...){
// do something
}
public void Method2(param1,param2,...){
// do something
}
}

Interface1 c1 = new ChildClass();
c1.Method1(..); // calls ChildClass.Method1

Interface2 c2 = new ChildClass();
c2.Method2(..); // calls ChildClass.Method2

~~~

> A project is a collection of files

> For date the universally accepted format is (1990-07-15)

---
## 🤝 Explicit interface implementation
Creating two methods with same signature in two different interfaces and implementing both interfaces in the same child class.

- *Explicit Interface implementation* is used to implement an interface method privatley; that means the interface method becomes as *private member* to the child class

- If a child inherits from two or more interfaces and there is a duplicate method. Use *Explicit Interface Implementation*
- You can use Explicit Interface Implementation to create private implementation of interface method, so you can create abstraction for those methods.

~~~
interface Interface1{
void Method1(param1,param2); // Same signature
}
interface Interface2{
void Method1(param1,param2); // Same signature
}

class ChildClass: Interface1, Interface2{
// To combine these in a child class we need to implement them explicitly using respective interface name
void Interface1.Method1(param1,param2){
// do something
}
void Interface2.Method1(param1,param2){
// do something
}
}

Interface1 c1 = new ChildClass();
c1.Method1(a,b); // calls interface1.Method1 at ChildClass

Interface2 c2 = new ChildClass();
c2.Method1(a,b); // calls interface2.Method1 at ChildClass
~~~

---

# 📁 12 Namespaces

## 🌐 Creating Namespaces
Namespaces are a collection of classes and *other types such as* interfaces, stuctures, delegate types and enumarations.

Main aim is to group these types as a single unit for a specific purpose. This helps for organization.

Although its best to have a namespace for each file. But can help for organization to reapply namespace grouping accross multiple.

We access the class via the namespace like so:
`NamespaceName.Typename reference`
`FrontOffice.CustomerEnquiry customer`

~~~
class Program
{
static void Main()
{
FrontOffice.CustomerEnquiry customerEnquiry = new FrontOffice.CustomerEnquiry();

}
}
~~~
~~~
//CustomerEnquiry.cs
namespace FrontOffice
{
//class that represents an enquiry by customer
public class CustomerEnquiry
{
}
}
~~~
~~~
//FrontOfficeExecutive.cs
namespace FrontOffice
{
//class that represents an executive to deal with customers at front office
public class FrontOfficeExecutive
{
}
}
~~~

> Although we have differnt files these are the same namespace

---

## 🎁 Nested Namespace
A namespace declared inside another namespace. The aim is to create a subgroup for better organization

> Its bad practice to have a class and namespace with the same name

To access this we need to say:
`OuterNamespaceName.InnerNamespaceName.Classname reference`
`HR.Mgr.IEmployee manager`
~~~
namespace HR
{

namespace Mgr
{

//interface that represents a manager, which inherits from IEmployee
public interface IManager : IEmployee
{
}
//class that represents an assistant manager, which inherits from IManager
public class AsstManager : IManager
{
}

}

//Other hr related types
}
~~~

---

## 📥 Importing Namespaces
You can use the *using* directive to import a namespace at the top of a file

This gets around having to repeat the long namespace name

- The *using* is a direective statement (top-level statement) that should be placed at the top of the file, which specifies the namespace from which you want to import everything.

~~~
using HR.Mgr;
class Program
{
static void Main()
{
IManager manager;
manager = new HR.Mgr.Manager();
}
}
~~~

---

## 🎭 Creating Using Alias
The *using alias* directive allows you to create an *alias name* for the namespace. Shortnames (nicknames) for the long name part.

> These aliases can only be used in one file

~~~
using m = HR.Mgr;
class Program
{
static void Main()
{
m.IManager manager;
manager = new HR.Mgr.Manager();

FrontOffice.CustomerEnquiry customerEnquiry = new FrontOffice.CustomerEnquiry();

}
}
~~~

---

## 🚀 Using Static
Meaning you can access all the static methods and properties directly without accessing the classname.

~~~
using static System.Console; // system is a static class
class Program
{
static void Main(){
WriteLine();
}
}
~~~

---

# 🏗️ 13 Partial & Static Classes

## 🧩 Partial Classes
A partial class is a class that spans accross multiple files. The way to do this is to define them as **partial** and wrap within a namespace

~~~
//file1
namespace Warehouse
{
public partial class Product{

}
}
~~~
~~~
//file2
namespace Warehouse
{
public partial class Product{

}
}
~~~
> This can make it easier for a team of developers to work on the same class.

---

## 🧩 Partial Methods
Partial Methods are *declared in one partial class* (just like abstract method) and *implemented in another partial class*, that have same name.

- Partial methods are private by default
- can only have void return type
- The can only be created in partial class or structs

~~~
//File1.cs
partial void GetTax(); // must have same signature
~~~
~~~
//File1.cs

partial void GetTax() // Notice body defined here
{
double tax = Cost * 10 / 100;
System.Console.WriteLine(tax);
}
~~~

---

## 🧱 Static Classes
Static class is class that can only contain *static members*
- Good if: you dont want even a single instance member.
- Avoids accidental creation of object for the class by making it a static class.
~~~
class Program
{
static void Main()
{
//access static fields
Console.WriteLine(Country.CountryName); // No object needed!
Console.WriteLine(Country.NoOfStates);
Console.WriteLine(Country.GetNoOfUnionTerritories());

Console.ReadKey();
}
}
~~~
~~~
public static class Country
{
public static string CountryName = "India";
public static int NoOfStates = 28;

public static int GetNoOfUnionTerritories()
{
return 8;
}
}
~~~

---

## 🎭 Enumerations
Enumeration is a collection of constants

Good If: *you dont want* to allow other developers to assign other value into a field/variable, other than list of values specified by enumeration.

Accessible like:
`EnumerationName.ConstantName`;

~~~
class Program
{
static void Main()
{
person.AgeGroup = AgeGroupEnumeration.Adult;
Console.WriteLine(person.AgeGroup);
}
}
~~~
~~~
public enum AgeGroupEnumeration : short //explicit DataType
{
Child,
Teenager,
Adult = 100, //You can also explictly add a value.
Senior
}
~~~
Each enumaration value has a stored integer value.

---

# 🏢 14 Structures

## 🏗️ Creating Structures
Two data types:

Value types: (Structures, Enumerations)
- Storing simple values
- Instances are called *structure instnaces* or *enumeration instances*
- Stored in the stack

Reference Types: (string,Classes,Intefaces,Delegates)
- Storing complex data / large amounts
- *Objects* (Class Instances etc)
- Instances (objects) stored in the *heap*

A structure is a *type* similar to *class* which can contain fields, methods, parameterized connstructors, properties and events.

Good if: you want to store a limited amount of fields 1 or 2. They are a little bit faster to store in stack. (no need to access heap)

- Structs do not support inheritance
- Cannot create refrence or object
- Can implement Interfaces
- Do not support virtual and abstract method
- Do not support destructors
- Internally derived from *System.ValueType* class `public struct Category:System.ValueType`
- Does not support init of "non static fields"
- Doesnt support *protected* and *protected internal* access modifier
- Do not support null values
~~~
class Program
{
static void Main()
{
//create structure instance
Category category = new Category();

//initialize fields through properties
category.CategoryID = 20;
category.CategoryName = "General";

//access methods
Console.WriteLine(category.CategoryID);
Console.WriteLine(category.CategoryName);
Console.WriteLine(category.GetCategoryNameLength());

Console.ReadKey();
}
}
~~~
~~~
public struct Category //accessible in the main method
{
//private field
private int _categoryID;
private string _categoryName;

//public fields
public int CategoryID
{
set
{
if (value >= 1 && value <= 100)
{
_categoryID = value;
}
}
get
{
return _categoryID;
}
}

public string CategoryName
{
set
{
if (value.Length <= 40)
{
_categoryName = value;
}
}
get
{
return _categoryName;
}
}

public int GetCategoryNameLength()
{
return this._categoryName.Length;
}
}
~~~


---
## Stuctures with Constuctors
- C# provides a default parameter-less constructor for every structure by default which initializes all fields.
- You can also create one or more user defined constructors
- Cach parameterized constructor must initialize all fields otherwise it will create compile-time error

~~~

Category category = new Category(30,"New Name");

~~~
~~~

public Category(int categoryID, string categoryName)
{
_categoryID = categoryID;
_categoryName = categoryName;
}

~~~

---
## Understanding Structures vs Class Practically

---

## Readonly Structures
Use readonly when:
- fields are read only
- all properties have get accessors
- there is parameterized constructor
- you dont want to allow any change
- methods can read fields but not change anything

- readonly is a new feature 8.0
- feature improces the perfomance

~~~
class Program
{
static void Main()
{
// create structure instance
Marvel m = new Marvel("Thanos");
Console.WriteLine(m.CharacterName); //property
m.PrintCharacterName(); //method
}
}
~~~
~~~
public readonly struct Marvel
{
private readonly string _characterName;

public string CharacterName {
get { return _characterName; }
}

public void PrintCharacterName()
{

System.Console.WriteLine(this.CharacterName);
// this._characterName = "abx"; // You cant do this

}

public Marvel( string CharacterName)
{
this._characterName = CharacterName;
}
}
~~~
---
## Primitive Types as Structures

-All primitive types except string are structures
- For example *sbyte* is a primitive type which is equivalant to "System.Sbyte" structure
- Its recommended to always use primitive types instead of structure

~~~
//create a structured variable
sbyte a = 10; // equivalant to System.Sbyte

//Create a reference variable and object of string
string b = "Hello"; //System.String
// same as
System.String b = "Hello";
~~~

---
# 15 System.Object class

## Overview
The **System.Object** is a pre-defined class, which is the *Ultimate super (base class)* in .net

class System.ValueType: (is parent to)
- Structures
- enumerations

All the classes and other types are inherited from this super class

The benefit of this is to *maintain type safety*

---

## Understanding & Overriding Methods of object class

~~~
//System.Object Class [Pre-defined]
namespace System{

class Object{
virtual bool Equals(object value); // returms true of both are equal but this can be overwritten
virtual int GetHashCode(); // numerical value to check whether two object are the same or not calling on each object and then comparing good for collections or hash sets
Type GetType(); //Not a virtual method so no override, this will return the typename (classs,interfaces)
virtual string ToString(); //Can be overridden
}

}
~~~

~~~
//Overiding System.Object class

class Program
{
static void Main()
{
//create an object of Person class
System.Object obj = new Person() { PersonName = "Scott", Email = "scott@gmail.com" };

//access methods
Console.WriteLine(obj.Equals(new Person() { PersonName = "Scott", Email = "scott@gmail.com" }));
Console.WriteLine(obj.GetHashCode());
Console.WriteLine(obj.ToString());
Console.WriteLine(obj.GetType().ToString());

Console.ReadKey();
}
}

~~~

---
## Key Points about object class
As per above

---

## Boxing
- Conversion from **Value-Type** to **Reference-Type**
- Boxing is done automatically
- Copies reference and primtives *from the stack to heap*
~~~

//primitive variable
int x = 10;

//boxing (value-type to reference-type)
object obj = x;

~~~
---

## Unboxing
Conversion from **Reference-Type** to **Value-Type**

~~~
//reference type variable
object obj = 10;

//unboxing (reference-type to value-type)
int x = (int)obj;
~~~
---

# 16 Generics

## Generic Classes
Generic class is a class, which contains one or more "type parameters"

-Can store various types of fields with respect to various types of object

- You must pass any data type (standard data / structure / class ) while creating object for the generic class.

Good if: you want the object to to decide the datatype. And you not sure of what datatype you are going to pass.

- You must define your datatype later when instantiating an object

- use generics when your not sure of the data types of the specific fields

~~~
//Generic class
public class User{ //DataType T (Just a generic name )

//generic field
public T RegistrationStatus; //must only store this data type in field
}
~~~

~~~
//Object of Generic Class - Example
//Create object of generic class
User user1 = new User();
User user2 = new User(); //Changing of type

user1.RegistrationStatus = 123;
user2.RegistrationStatus = false;

Console.WriteLine(user1.RegistrationStatus);
Console.WriteLine(user2.RegistrationStatus);
~~~

---
## Multiple Generic Parameters
We can further specify constraints at object instantiation
~~~
//create object of generic class
User user1 = new User(); // first and second types must be of int
User user2 = new User(); // first bool second string

//set value into generic field
user1.RegistrationStatus = 1234;
user2.RegistrationStatus = false;

user1.Age = 22;
user2.Age = "35 - 40";
~~~
~~~
//Generic class
public class User // Specify we have two types
{
//generic field
public T1 RegistrationStatus;

//another generic field
public T2 Age;
}
~~~

---

## Generic Contstraints
Are the expectations or restrictions on the paramters. Generic constraints are used to specify the allowed types to be accepted in the *generic type parameter*

> Abstract means you do not want to create an object of this class directly

~~~
//create object of generic class
MarksPrinter mp = new MarksPrinter(); // Must be student or a child class of
mp.stu = new GraduateStudent() { Marks = 80 };
mp.PrintMarks();
~~~
~~~
//generic class with constraints (want to accept Student or its child classes only)
public class MarksPrinter where T : Student // Here we could use class simply or be more specific make a specific class
{
public T stu;

public void PrintMarks()
{
Student temp = (Student)stu; // Typecast class into field
System.Console.WriteLine(temp.Marks);
}
}
~~~

You could contingue on to specify more constraints like so

`public class MarksPrinter where T : Student where T2: employee`

---

## Generic Methods
Generic method is a method that has one or more generic parameters.

You can restrict what type of data types (class names) allowed to be passed when creating the object

Good if: you are not sure what type of value you want to revieve.

Suppose we have two classes employee and student with some methods. We can define a generic class that accepts these external methods.
~~~
//Program.cs
static void Main()
{
Sample sample = new Sample();
Employee emp = new Employee() { Salary = 1000 };
Student stu = new Student() { Marks = 10 };

//sample.PrintData;
sample.PrintData(stu); // this gets passed into obj

}
~~~
~~~
//Clas1.cs
public class Employee
{
public int Salary;
}

public class Student
{
public int Marks;
}

//a class with generic method
public class Sample
{
//generic method
public void PrintData(T obj) where T : class
{
if (obj.GetType() == typeof(Student)) // checks to see if method supplied is of student
{
Student temp = obj as Student;
System.Console.WriteLine(temp.Marks); // we can then access the marks property
}
else if (obj.GetType() == typeof(Employee))
{
Employee temp = obj as Employee;
System.Console.WriteLine(temp.Salary); // we can then access the salary property
}
}
~~~

---

# 17 Handling Null

## Nullable types
There are two types:

Value types: (structures, enumerations)
- Are by default non-nullable
- Non nullable tpyes dont support null values

~~~
Nullable x = null
int? x = null
~~~

~~~
namespace namespace1
{
class Person
{
public int? NoOfChildren; // this structure is now nullable
}
class Program
{
static void Main()
{
//create object
Person p1 = new Person() { NoOfChildren = null };
}
}
}
~~~

References types: (classes, interfaces)
- by default nullable types
- support null values
- dont require the below syntax

> Sometimes in the realworld if this value is not equal to null you will need to access the value of a nullable type, then its required to use `value`. And check using `HasValue`
~~~
if (p2.NoOfChildren.HasValue)
{
int x = p2.NoOfChildren.Value;
Console.WriteLine(x);
}
~~~

---
## Null Coalescing Operator
Short hand to check if the value is null or not
- The 'null coalescing operator' checks whether the value is null or not.
- It returns the left-hand-side operand if the value is not null.
- It returns the right-hand-side operand if the value is null.

~~~
// variableName ?? valueIfNull
Console.WriteLine(p2.NoOfChildren ?? 0); //if value is not equal to null set to 0
~~~
> When using Null Coalescence the datatype of alternative should be the same as the actual field

---

## Null Propagation operator
Used for reference variables..

-The "Null Propagation Operator ( ?. ) and ( ? [] ) checks the value of left-hand operand whether it is null or not.
-It returns the right-hand-side operand (property or method), if the value is not null.
-It returns null, if the value is null.
-It accesses the property or method, only if the reference variable is "not null"; just returns "null", if the reference variable is "null".

-We can invoke desired member (property or method) after checking if null.

~~~
referenceVariable?.fieldName;
-- is same as --
(referenceVariable == null)? null : referenceVariable.fieldName;
~~~
~~~
class Person
{
public int Age;
}

class Program
{
static void Main()
{
//p1 is null
Person p1 = null;

//print age

Console.WriteLine( p1?.Age );//checks the value of left returns the right if not null then trys to access its field property or method

Console.ReadKey();
}
}
~~~
> Avoids Null reference Exception
---

# 18 Extension Methods & Patterns

## Extension Methods
Method is injected into existing class without modifying source code of that class `GetDiscount(this Product product)`

(see pdf)[_resources\Extension+Methods+Cheatsheet.pdf]

- Must be a static class only with static method. This will get specified as instance method via *this*.

- cannot use this inside static method
- Dont forget to import the namespace for which the extension class is different

~~~
Product p = new Product() { ProductCost = 1000, DiscountPercentage = 10 };

//call the extension method
Console.WriteLine(p.GetDiscount());
~~~
~~~

namespace ExtensionsNamespace
{
//static class for extension method
public static class ProductExtensions
{
//extension method for Product class
public static double GetDiscount(this Product product) // instance method via *this*.
{
return product.ProductCost * product.DiscountPercentage / 100;
}
}
}

~~~

---
## Pattern Matching
Allows you to decalare a vairable while checking the data type of reference and automatically type casts the ref variable into a specified data type (class)
(see pdf)[_resources\Pattern+Matching+Cheatsheet.pdf]

~~~
object greeting = "Hello, World!";
if (greeting is string message) //
{
Console.WriteLine(message.ToLower()); // output: hello, world!
}
~~~
---
## Implicitly Typed Variables
(see pdf)[_resources\Implicitly+Typed+Variables+Cheetsheet.pdf]
~~~
//implicit assignment
var variableName = value;
~~~
~~~
// Implicit type usage
// Using var keyword to shorten a legnthy variable
var p = new namespace1.namespace2.namespace3.Person() { PersonName = "Harsha" };
//calling a method on written type
var p2 = "Harsha".ToUpper(); //Datatype is implicit as string
// You cant do this it must be intialized
//var p3;
~~~
- You cant decalre multple
- not possbile either to assign to null
---

## Dynamically Typed Variables
Variables that are declare with *dynamic* keyword and can potentially change data type
(see pdf)[_resources\Dynamically+Typed+Variables+Cheatsheet.pdf]
Accepts any datatype.
Good if: your not sure what datatype you want to store use `dynamic`
- C# will not type check this

~~~
//dynamically typed variable
dynamic x;

x = 100;

x = "Hello";

x = new Student() { StudentName = "Harsha" };
Console.WriteLine(x);

~~~
---
## Inner Classes
We can create all inter-related classes of a class, "inner-classes"
(see pdf)[_resources\Inner+Classes+Cheatsheet.pdf]

Syntax: `outerclass.innerclass`

~~~
class ClassName
{
class InnerClassName
{
Members here
}
}

~~~
- By default, inner class is "private"
- Outer class needs object to access inner class
- You cant do both
~~~
//accessing an inner class from the class
//outer class
public class MarksCalculation
{
public void CalculatePercentage(Student s)
{
//create object of inner class
CalculationHelper ch = new CalculationHelper();
s.Percentage = ch.Multiply( s.SecuredMarks / s.MaxMarks, 100);
}

//inner class
public class CalculationHelper
{
public double Multiply(double n1, double n2)
{
return n1 * n2;
}
}
}
~~~
---
# 19 Garbage Collection, Destructors, IDisposable

## Garbage Collection & Generations
Garbage Collection is a process of deleting
objects from memory, to free-up memory;
so the same memory can be re-used. Its envoked autmatically when freespace is required
Optionally can call `GC.Collect()` explicitly

(see pdf)[_resources\Garbage+Collection+Cheatsheet.pdf]

---

## Destructors
Destructor is a special method of the class, which is used to close un-managed resources (such as database connections and file connections), that are opened during the class execution. This happens automatically.

There are two tpyes of resources in c#:
Managed:
Objects created by Common Language Runtime
Participate in garbage collection

Unmanaged:
Objects not created by Common Language Runtime
Eg: File Streams & DB Connections

Good if: When we want to close db connections and file connections to avoid leakage.

Usually called at the end of a class

(see pdf)[_resources\Destructors+Cheatsheet.pdf]

~~~
public class Sample
{
//constructor
public Sample()
{
//file & db connection logic here
Console.WriteLine("File is opened");
}

//destructor
~Sample()
{
//file & db closing logic here
Console.WriteLine("File is closed");
}
}
~~~
---
## IDisposable
Is a predefined interface of *System* namespace, has a method called *dispose* which is used to close unmanaged resources that are created during the life-time of the object.

- can be used as alternative to destructor
- suppose you have a project running for many hours this allows developers to jump in and free up memory
- With dispose method you need not wait till the end of running the application
- Particularly in real world projects within business access layer /database layer you will find *dispose*

> To move sequentially thought the program you can use the **F10 Command**
- Use the using only in for the class that contains the dispose method with Databse method is placed

(see pdf)[_resources\IDisposable+Cheatsheet.pdf]
~~~
/*
Output
Database connected.
Reading data from database
Database disconnected
Some other work here
*/
namespace IDisposableExample
{
class Program
{
static void Main()
{
//create object using "using structure"
using (Sample s = new Sample())
{
//This will jump from the constructor, to any specified method like below and finally to the dispose method
s.DisplayDataFromDatabase();

}

Console.WriteLine("Some other work here");

Console.ReadKey();
}
}
}

~~~
~~~
namespace ClassLibrary1
{
public class Sample : System.IDisposable
{
//constructor
public Sample()
{
Console.WriteLine("Database connected.");
}

//method
public void DisplayDataFromDatabase()
{
Console.WriteLine("Reading data from database");
}

//Dispose
public void Dispose() //called automatically no need to wait untill main
{
Console.WriteLine("Database disconnected");
}
}
}
~~~
3 steps to this process:
1. Implement the called `public class Sample : System.IDisposable`
2. Implement the Dispose method
3. Required to use *using* stucture and at compilation time this will close via dispose mehtod

---

## Using Declaration
- You can prefix "using" keyword before the local variable declaration,in order to call "Dispose" method when that variable goes out of scope.

This the same as prebious example but rather than putting it in a () brackets were are using a declarations. To specify methods you can simply instantiate them after creating reference variable. Automatically `Dispose()` will be called.

~~~
using Sample s = new Sample();
s.DisplayDataFromDatabase(); //instantiate them after creating reference variable.

~~~

This feature is only available in c# 8.0. However you can change this value manually. Right click on the project solution and open in file explorer. Use something else than visual studio for this. Find the file ext .csproj and form here you can modify the language version 8.0. You may need to reload afterwards.

> F11: will take you to every line including your function body, but F10 allows to move from one line to the the immediate next line

If you dont use using `dispose` will have to be declared explicitly.

---

# Delegates & Events

## Creating Delegates
**Delegate type** is a **type** that represents methods that have specific parameters and return type.

The *delegate* object is an object that stores a reference (address) of a specific method of a specific class with compatibile parameters and return type

(see pdf)[_resources\Delegates+Cheatsheet.pdf]

- Helpfull for building events
- They are the building blocks of events
- References one or more methods *System.Delegate*
- Each delegate will have a specific name
- In here you can store a reference to one or more methods
- The delegate type is more like a condition
- *Single-cast delegate* object can have a return type

This is like queing up (delegating responsibility) methods from a class (sample) injecting them into a delegate type then `invoke`ing them passing paramters.

~~~
using System;
using ClassLibrary1;

namespace SingleCastDelegatesExample
{
class Program
{
static void Main()
{
//create object of Sample class
Sample s = new Sample();

//create delegate object (or) delegate
MyDelegateType myDelegate;

//add/pass method reference to delegate
myDelegate = new MyDelegateType(s.Add);

//invoke method using delegate object
Console.WriteLine(myDelegate.Invoke(30, 40)); //Here we need to match the number of parameters

Console.ReadKey();
}
}
}
~~~
~~~
using System;

namespace ClassLibrary1
{
public class Sample
{
//target method
public int Add(int a, int b)
{
int c = a + b;
return c;
}
}
}

~~~
~~~
using System;
namespace ClassLibrary1
{
//create delegate type
public delegate int MyDelegateType(int a, int b);
}
~~~

> Notice that both the *delegate* and *sample class* are within the same namespace.

---

## Multicast Delegates
When you invoke multiple delegates. These can be called after passing the refs of a bunch of target methods then using `myDelegate.Invoke(40, 10);`
- As its multicast delegate we will not be returning anything and we can set our delegate type to be `void`

- In our sample class we also now have multiple methods

~~~
using System;
using ClassLibrary1;

namespace MultiCastDelegatesExample
{
class Program
{
static void Main()
{
//create object of Sample
Sample s = new Sample();

//create reference variable of MyDelegateType
MyDelegateType myDelegate;

//add ref of first target method
myDelegate = s.Add;

//add ref of second target method
myDelegate += s.Multiply;

//invoke both target methods; first Add method; and then Multiply method
myDelegate.Invoke(40, 10);

Console.ReadKey();
}
}
}
~~~
~~~
using System;

namespace ClassLibrary1
{
public class Sample
{
//target method 1
public void Add(double a, double b)
{
double c = a + b;
Console.WriteLine("Addition is: " + c);
}

//target method 2
public void Multiply(double a, double b)
{
double c = a * b;
Console.WriteLine("Multiplication is: " + c);
}
}
}
~~~
~~~
using System;

namespace ClassLibrary1
{
//delegate type
public delegate void MyDelegateType(double a, double b);
}

~~~

Rules:
- paramters should be same
- no return value

> We really only use delegates in conjunction with events. Hardley ever directly.

---
## Events
Event is basically a *delegate*. A multicast delegate that stores one or more methods and invokes them when the event is raised.

They can only be raised in the same class in which they are created.

(see pdf)[_resources\Events+Cheatsheet.pdf]

Events are achieved through interactions between a *publisher class* and a *subscriber class* (Publisher informs subscriber)

Think of this like a bank account class with an event that gets the interest rate. When the interest rate is changed (publisher class) it informs the bank account calculate interest method to perfom an up to date calculation.

Publisher class:
- Sends (raises events)

Subscriber class:
- Recieves (or subscribes or handles) events

- we can only raise the event from the class of witch it has been created

Total Of 4 steps:
1. Publisher class has event
2. Subscriber class has to subscribe to event
3. Publisher class has to raise event
4. Then corresponding eventh andler method (add) must be executed in subscriber class

- this is also called the notification or publisher/subscriber pattern
- events are also found in button / form class. Button raises event. Form subscribes to event.

~~~
//Program.cs
using System;
using ClassLibrary;

namespace EventsExample
{

class Program
{
static void Main()
{
//Create object of subscriber
Subscriber subscriber = new Subscriber();

//Create object of publisher
Publisher publisher = new Publisher();

//handle or subscribe to the event
publisher.myEvent += subscriber.Add; // store/subscrive reference of add method in myevent

//invoke the event
publisher.RaiseEvent(13, 12);

Console.WriteLine();

}
}
~~~
~~~
//Publisher.cs
using System;

namespace ClassLibrary
{
//delegate type
public delegate void MyDelegateType(int a, int b); // this represents the parameters and delegate type of event

//publisher
public class Publisher
{
//private delegate
private MyDelegateType? myDelegate; //this will store one or more methods

//step 1: create event
public event MyDelegateType myEvent //allowing external to subscribe to event
{
add
{
myDelegate += value; //reference will be added to reference mydelgate above
}
remove
{
myDelegate -= value;
}
}

public void RaiseEvent(int a, int b) //raise event in same class only
{
//step 2: raise event
if (this.myDelegate != null) //if nobody has subscribed to the event its default is null
{
this.myDelegate(a, b); // 2 parameters in delegate type
}
}
}
}
~~~
~~~
//Subscriber.cs
using System;
using ClassLibrary;

namespace EventsExample
{

class Subscriber //The aim of this class is only to listen in for when publisher raises event
{
// here we can assign the reference of one or more methods to the event
//Target method
public void Add(int a, int b)
{
Console.WriteLine(a + b);
}
}

}

~~~
---
## Auto-Implemented Events
Creating event with auto-generated add-accesor and remove accessor
Shortcutt syntax in order to create event
Good: In the case, you need not create "add", "remove" accessors, the compiler does this automatically.
just like *Auto-Implemented property initializers*

~~~
using System;

namespace ClassLibrary1
{
//delegate type
public delegate void MyDelegateType(int a, int b);

//publisher
public class Publisher
{
//c# compiler automatically creates private delegate field

//step 1: create event
public event MyDelegateType myEvent;

//c# compiler automatically create the code for add and remove accessors
public void RaiseEvent(int a, int b)
{
//step 2: raise event
if (this.myEvent != null) // then just call my event itself rather than the private delegate
{
this.myEvent(a, b);
}
}
}
}
~~~

The Add method in subscriber is also known as the **event handler**

- Disadvantage of this is we cant define custom logic for our **add access** & **remove accessor**

---
## Anonymous Methods
These are anonymous methods **name-less methods** that can be invoked by using the delegate variable or an event.

Good if: you want to create a method with very few lines of code
🚀 New feature of c# 2.0
(📄 see pdf)[_resources\Anonymous+Methods+Cheatsheet.pdf]

~~~
public delegate void Print(int value);

static void Main(string[] args)
{
Print print = delegate(int val) {
Console.WriteLine("Inside Anonymous method. Value: {0}", val);
};

print(100);
}
~~~

---
## 🐑 Lambada Expressions

You use a lambda expression to create an anonymous function. Use the lambda declaration operator => to separate the lambda's parameter list from its body. A lambda expression can be of any of the following two forms:
Expression:
(input-parameters) => expression
Statement:
(input-parameters) => { sequence-of-statements> }

~~~
Func square = x => x * x; //lambda expressions
Console.WriteLine(square(5));

Action greet = name => //lambda statement
{
string greeting = $"Hello {name}!";
Console.WriteLine(greeting);
};

greet("World");
~~~
- Similar to anonymous methods
- Similar to delegate instead we use '=>'
---

## 🎯 Func
Delegate with parameters and return
*Func* is a pre-defined generic delegate which can be used to create events quickly
- 0 -16 parameters
- must have predefined value

(📄 see pdf)[_resources\Func+Cheatsheet.pdf]

`public delegate TResult Func(T arg);`

~~~
// Func Syntax: public delegate TResult Func(T arg);
Func plusone = number => number + 1;
Console.WriteLine(plusone(3));
~~~

---
## 🎬 Action
Predefined delegate in c# (mostly same as func without a return type)
(📄 see pdf)[_resources\Action+Cheatsheet.pdf]

~~~
class Program
{

static void Main()
{
Action doWorkAction = new Action(DoWork); //by default is void
doWorkAction(); //Print "Hi, I am doing work."
}

public static void DoWork()
{
Console.WriteLine("Hi, I am doing work.");
}

}

~~~

---
## 🎲 Predicate
Delegate with one parameter and boolean return
(📄 see pdf)[_resources\Predicate.pdf]

~~~
class Program
{
static bool IsUpperCase(string str)
{
return str.Equals(str.ToUpper());
}

static bool IsPositiveNumber(int num)
{

if(num < 0) { return false; } else { return true; }

}

static void Main()
{

Predicate isUpper = IsUpperCase;
bool result = isUpper("hi");
Console.WriteLine(result);

Predicate isPos = IsPositiveNumber;
bool result2 = isPos(-1);
Console.WriteLine(result2);

}

}
~~~
---
## 🎉 Event Handler
Delegate for data exchange in events. Predefined delegate type
~~~

//Step 1. Declare a delegate with the signature of the encapsulated method
public delegate void MyDelegate(string input);

//Step 2. Define methods that match with the signature of delegate declaration
class Class1 {

public void delegateMethod1(string input)
{

Console.WriteLine("Hi im delegate method 1 with input "+ input);

}

public void delegateMethod2(string input)
{

Console.WriteLine("Hi im delegate method 2 with input " + input);

}

}

//Step 3. Create delegate object and plug in the methods
class Class2
{

public MyDelegate createDelegate()
{
Class1 c2 = new Class1();

MyDelegate d1 = new MyDelegate(c2.delegateMethod1);
MyDelegate d2 = new MyDelegate(c2.delegateMethod2);
MyDelegate d3 = d1 + d2;
return d3;
}

}

//Step 4. Call the encapsulated methods through the delegate
class Class3
{
public void callDelegate(MyDelegate d, string input)
{
d(input);
}
}

class Driver
{

static void Main()
{

Class2 c3 = new Class2();
MyDelegate d = c3.createDelegate();
Class3 c4 = new Class3();
c4.callDelegate(d, " Calling the delegate");

}

}
~~~
---
## 🌳 Expressions Trees
Introduced in c# 3.0
- Expression Tree is a collection of delegates represented in tree-like structure.
- Expression Tree only executes when we compile and execute it.
- Expression Trees support all delegate types such as Func, Action, Predicate or
custom delegate types.
- Used always internally used in the concept of Linq
(📄 see pdf)[_resources\Expression+Trees+Cheatsheet.pdf]

~~~
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace ExpressionTreesExample
{
class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
}

class Program
{
static void Main()
{
//Create object of Student class
Student s = new Student() { StudentID = 101, StudentName = "Scott", Age = 15 };

//Create expression tree with Func
Expression> expression = st => st.Age > 12 && st.Age < 20;

//Compile expression using Compile method to invoke it as Delegate
Func myDelegate = expression.Compile();

//Execute the method
bool result = myDelegate.Invoke(s);

Console.WriteLine(result);
Console.ReadKey();
}
}
}

~~~

---
## 🎁 Expression Bodied Members
*Expression Bodied Members* concept allows the developer to use "Inline Lambda Expressions" to create methods, property accessors, constructors, destructors, indexers in a class
- provide a minimal and concise syntax to define properties and methods.
- May or may not have parameters
- May or maynot have return value

> its convenient only if you have some simple code to convert to an expression

(📄 see pdf)[_resources\Expression+Bodied+Members+Cheatsheet.pdf]
~~~
//In its simplest form
public class Employee
{
public void DisplayName(string name) => Console.WriteLine(name); //Expression bodied member note use of "=>"
}
class Program
{
static void Main()
{
Employee employee = new Employee();
employee.DisplayName("Joey");

}
~~~
~~~
public class Employee
{
private string FirstName;
private string LastName;
public Employee(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string GetFullName() => $"{FirstName} {LastName}";
public override string ToString() => $"{FirstName} {LastName}";
public void DisplayName() => Console.WriteLine(GetFullName());
}
class Program
{
static void Main()
{
Employee employee = new Employee("Pranaya", "Rout");
employee.DisplayName();
Console.WriteLine(employee);
Console.WriteLine("Press any key to exists");
Console.ReadKey();
}
}
~~~

---
## 🎭 Switch Expression

Switch Expression is a short-form of "switch-case", which is used to check
the value of source variable; assign value into result value based on the
value of source variable.

(📄 see pdf)[_resources\Switch+Expression+Cheatsheet.pdf]

~~~
var operation = 2;

var result = operation switch
{
1 => "Case 1",
2 => "Case 2",
3 => "Case 3",
4 => "Case 4",
};

Console.WriteLine(result);

~~~

The variable used in switch expression is now coming before the switch
keyword.
- Colon (:) and case keyword are replaced with arrows (=>). Which makes the
code more compact and readable.
- The default case is now replaced with a discard(_).
- And the body of the switch is expression, not a statement.
- **Switch Expression** returns the result value based on the matching case.
- It is only meant for getting a specific result value; doesn't let you to write multiple statements.

---

# 21 Arrays

## 🎨 Creating arrays
Array is a group of multiple values of same type. Arrays are stored in continuous-memorylocations in 'heap'

(📄 see pdf)[_resources\Arrays+Cheatsheet.pdf]

Each value of array is called "element".
› All the elements are stored in continuous memory locations.
› The address of first element of the array will be stored in the "array
reference variable".
› The "Length" property stores count of elements of array. Index starts from
0 (zero).
› Arrays are treated as objects of "