Basic

Glossary

Private fields: 
Can only be accessed by methods in the class (via getter and setter) and 
they are not accessible by subclasses or instantiation.

Protected fields:
Can only be accessed by methods in the class and by subclasses.

Read-only fields:
Set at runtime at constructors and can't be changed.

Method overloading:
When you have different versions of method 

Method override:
when you replace a method

Generic can only store one type
Non generic can store many types

TryGetValue

if (!xlRow.Cell(SchemesExcelColumn.Version).TryGetValue(out int version))
{
    version = 1;
}
// If successfull, you get version. If not, you get version = 1 as default
            
       
if (results.TryGetValue(conditionBankId, out var conditionTemplateDtos))
{
    conditionTemplateDtos.Add(conditionTemplateDto);
}
else
{
    results.Add(conditionBankId, 
    new List<ConditionTemplateDto> {conditionTemplateDto});
}
// If successful of retrieving the conditionBankId (key) in RESULTS,
// you out the list of conditionTemplateDtos and add the conditionTemplateDto
// If fail, you add the RESULTS with conditionBankId as key 
// and initiliaze the new list as value

Verbatim String

// verbatim ignore \n
Console.WriteLine(@"you \n have no power here");
// good example is 
// Console.WriteLine(@"C:\User\Admin\Doc\Super Cool.png");
// without verbatim, it will escape due to \ and give error

Console.WriteLine("you \n have power here");

Null

Data types by default cannot have a value of null. 
When null is needed, add question mark:

int? randNum = null;

Casting

// If you want to cast from one type to another - conversion
long num1 = 1234;
int num2 = (int)num1;
 
Console.WriteLine("Orig : {0} Cast : {1}", num1.GetType(), num2.GetType());
//Int64 and Int32

Pass by Value vs Pass by Reference

// By default values are passed into a method
// and not a reference to the variable passed
// Changes made to those values do not effect the variables outside of the method

// To pass by reference:
int num1 = 10;
int num2 = 20;
 
Console.WriteLine("Before Swap num1 : {0} num2 : {1}", num1, num2); // 10 and 20
Swap(ref num1, ref num2);
Console.WriteLine("After Swap num1 : {0} num2 : {1}", num1, num2);  // 20 and 10

public static void Swap(ref int num1, ref int num2)
{
  int temp = num1;
  num1 = num2;
  num2 = temp;
}



static void Main(string[] args)
{
	int a = 1;
	int b = a;

	Console.WriteLine(a); // 1
	Console.WriteLine(b); // 1
	
	a = 5;

	Console.WriteLine(a); // 5
	Console.WriteLine(b); // 1, not affected by the change

	Test(a);

	Console.WriteLine(a); // 5, not affected by the method
	Console.WriteLine(b); // 1

	int[] c = { 10 };
	int[] d = c;

	Console.WriteLine(c[0]); // 10
	Console.WriteLine(d[0]); // 10

	d[0] = 20;

	Console.WriteLine(c[0]); // 20 // affected by the change
	Console.WriteLine(d[0]); // 20
}
static void Test(int a)
{
	a = 100;
}

Params Modifier

static double GetSumMore(int num1, int num2, params double[] nums)

GetSumMore( 1, 2, 3, 4) // num1 is 1, num2 is 2 and the rest is params (3,4)

Array

int[] luckyNumbers = { 4,  7, 10 }
var employees = new[] { "Mike", "Paul", "Rick" };					
// Create array with values

string[] friends = new string[5];					
// Create array with empty values with length of 5

//Multi-Dimensional Array
int[ , ] numberGrid = { 	
	{1, 2 },
	{3, 4 },
	{5, 6 }
};	

int [ , ] = new int [2, 3]			
// Create 2D array - 2 row and 3 columns (elements)

Exception Handler - Prevent program from exiting and handle the error

try {
  // Your code block
}					
catch (Exception e) {					
	Console.WriteLine (e.Message)				
}					
					
// OR
					
catch (FormatException e) {
  // Your code block to handle FormatException					
}					
catch (DivideByZeroException) {					
  // Your code block to handle DivideByZeroException										
}					
finally {					
  // Always get executed no matter what		
}

Constructor

class Book					
{					
  public string title;					
  public string author;					
  public int pages;					
					
	// You can have many constructor inside a class, including empty constructor				
	public Book (string aTitle, string aAuthor, int aPages ) 
	{				
		title = aTitle;			
		author = aAuthor;			
		pages = aPages;			
	}
}


// constructor overloading - Use with caution as it clutter the code
class Customer
{
	public int Id;
	public string Name;
	public readonly List<Order> Orders = new List<Order>(); 
	// initilize customer with order list and readonly prevent re-initilization
	
	public Customer (int id)
	{
		this.Id = id;
	}
	
	public Customer(int id, string name) : this(id) // called constructor with id
	{
		this.Name = name
	}
}

Getter and Setter

// Using getter as read-only property					
class Player 				
{				
  private int _heatlh = 100			
  public int health 			
	{			
		get 		
		{		
			return _health	
		}		
	}			
				
	public void Damage (int _dmg)			
	{			
		_health -= _dmg		
	}			
}				
				
Player tom = new Player();				
tom.Damage(10)               // OK
tom.health = 80              // Not OK as it is Read Only
Console.Writeline(tom.health)// Print 90



// Using setter to prevent invalid value in object creation				
class Movie					
{					
  public string title;					
  public string director;					
  private string rating;					
					
					
  public Movie (string aTitle, string aDirector, string aRating ) {					
	  title = aTitle;				
	  director = aDirector;				
	  Rating = aRating;				
  }					
					
  public string Rating {					
	 get { return rating; }				
	 set {				
	  if (value == "G" || value == "R" || value == "NR") {				
		  rating = value			
	  }	else {				
		  rating = "NR"			
	  }				
  }					
}			

// You can have the getters and setters likt this and also set the default value
public string Owner { get; set; } = "No Owner";				

Static - Class Static Attribute and Static Method and Static Class

// Class static attribute is about the class and not the object. 
// So, static attribute is shared in all instances.							
class Song							
{							
  public string title;							
  public string artist;
  public static int songCount = 0;						
							
	public Song (string aTitle, string aArtist ) {						
		title = aTitle;					
		artist = aArtist;	
		songCount++					
	}						
	
	public int getSongCount( ) {						
		return songCount;					
	}						
}							
							
Song holiday = new Song ("Holiday", "Green Day", 200);
// Another way to create object
Song holiday = new Song () { title= "Holiday", artist = "Green Day" }							
							
Console.WriteLine(Song.songCount)					// 1		
Console.WriteLine(holiday.songCount )			// Not accessible		
Console.WriteLine(holiday.getSongCount()) // Onlt accesible through object method		
							
							
// Static Methods & Class													
							
static class usefulTools // Static Class means you cannot create an instance
{							
	public static void SayHi( string name )
	// without the word static, you need to create an object to access the method		
	{						
		ConsoleWriteLine("hi" + name)										
	}						
}							
							
UsefulTools.SayHi("Ben")					
// So you can just call it from the class without creating an object

Inner Class

 // You can create inner classes that are normally helper classes for the outer 
 // class because it can access private members of the outer class
 class Animal {
   public class AnimalHealth {
     public bool HealthyWeight(double height, double weight) {
       double calc = height / weight;
       if ((calc >= .18) && (calc <= .27)) {
         return true;
       }
       else return false;
     }
   }
 }
 
Animal.AnimalHealth getHealth = new Animal.AnimalHealth();
 
Console.WriteLine("Is my animal healthy : {0}", getHealth.HealthyWeight(11, 46));

Inheritance - Is-A relationship (Dog Class is Animal Class)

// Italian chef override method of normal chef
public override void MakeSpecialDish() {
  Console.WriteLine("Cook Spagethi");
}

// Normal chef method that can be overriden by sub-class
public virtual void  MakeSpecialDish ()	{		
  Console.WriteLine("Cook BBQ Ribs");
}

Aggregation or Delegate - Has-A relationship (Animal Class has a Animal Id Info Class)

class Animal {
    protected AnimalIDInfo animalIDInfo = new AnimalIDInfo();
  
    public void SetAnimalIDInfo(int idNum, string owner) {
        animalIDInfo.IDNum = idNum;
        animalIDInfo.Owner = owner;
    }
}

class AnimalIDInfo {
    public int IDNum { get; set; } = 0;
    public string Owner { get; set; } = "No Owner";
}

Polymorphism

class Animal {
  public void MakeSound() {
    Console.WriteLine($"{Name} says {Sound}");
}

// You can define 2 Animal objects but have one actually be a Dog type. 
Animal monkey = new Animal() { Name = "Happy", Sound = "Eeeeee" };
 
Animal spot = new Dog() { Name = "Spot", Sound = "Wooooff", Sound2 = "Geerrrr" };

spot.makeSound() // spot says Wooooff (without the sound2)

// With polymorphism with virtual and override
// This is an example of how Polymorphism allows a subclass to override a method
// in the super class and even if the subclass is defined as the super class
// type the correct method will be called
class Animal {
  public virtual void MakeSound() {
    Console.WriteLine($"{Name} says {Sound}");
}

class Dog : Animal {
  public override void MakeSound() {
    Console.WriteLine($"{Name} says {Sound} and {Sound2}");
  }
}

spot.makeSound() // spot says Wooooff and Geerrrr

// Another example of polymorphism
abstract class Shape {} // abstract is a clss that you don't want to instantiate

class Circle : Shape {}
class Rectangle : Shape {} 

Shape[] shapes = {new Circle(5), new Rectangle(4,5)};
foreach(Shape s in shapes) {
  Circle testCirc = s as Circle; // Use "as" to check if an object is of a specific type
  if(testCirc == null) {
    Console.WriteLine("This isn't a Circle");
  }
  if(s is Circle) { // Use "is" to check the data type
    Console.WriteLine("This isn't a Rectangle");
  }
}

List, Dictionary, Tuple

// Array with dynamic size use List and it can only consist of one data type
List <int> numbers = new List<int> ();
number.Add(1); // OK
number.Add("Hello"); // Not OK

// Dictionary<TKey, TValue>
Dictionary<string, int> myDictionary = new Dictionary<string, int>();
myDictionary.Add("a", 100);
myDictionary.Add("b", 200);
Console.WriteLine(myDictionary["a"]); // 100

// Tuple, carry different type of data 
public Tuple<string, int> Math(int a, int b)
{
	string c = "Hello World";
	int d = a * b;
	return Tuple.Create(c, d);
}
static void Main(string[] args)
{
	Program p = new Program();
	var obj = p.Math(10, 20);
	Console.WriteLine(obj.Item1); // Hello World
	Console.WriteLine(obj.Item2); // 200
}

// New way to create tuple
public (string Hello, int Multiply) Math(int a, int b)
{
	string c = "Hello World";
	int d = a * b;
	return (c, d);
}
static void Main(string[] args)
{
	Program p = new Program();
	var obj = p.Math(10, 5);
	Console.WriteLine(obj.Hello);
	Console.WriteLine(obj.Multiply);
} 

Enum

enum Breed { Bulldog, Boxer, Chihuahua };		

class Dog
{		
	public Breed breed;	
	public Dog(Breed _breed)	
	{	
		breed = _breed
	}		
}		

Dog spotty = new Dog(Breed.Bulldog / Breed.Boxer/ Breed.Chihuahua)
Console.WriteLine(spotty.breed);	


enum CarColor : byte // initialize to byte, the default is integer
{
  Orange = 1, // initialize to 1, the default is 0
  Blue,
  Green,
  Red,
  Yellow
}

static void Main(string[] args)
{
  CarColor car1 = CarColor.Yellow;
  PaintCar(car1);
}

static void PaintCar(CarColor cc)
{
  Console.WriteLine("The car was painted {0} with the code {1}",
  cc, (byte)cc);
}

Interface

Interface is like a contract... Why not use base class? Because you can derive from multiple interfaces

Generics

Handle unknown data types

// Generic method inside non-generic class						
class Utility						
{						
	public static bool CompareValues<T01, T02> (T01 value1, T02 value2)					
	{					
		return value1.Equals(value2);				
	}					
	public static bool CompareTypes<T01, T02> (T01 type1, T02 type2)					
	{					
		return typeof(T01).Equals(typeof(T02));				
	}					
}						
						
Console.WriteLine(Utility.CompareValues(10, "Hello"));		 // FALSE
Console.WriteLine(Utility.CompareTypes("World", "Hello")); // TRUE

Dependency Injection - Add Singleton, Add Scoped and Add Transient

Service Type

In the scope of a given HTTP request

Across different HTTP request

Scoped Service

Same Instance

New Instance

Singleton Service

Same Instance

Same Instance

Transient Service

New Instance

New Instance

Defensive Programming - Mosh

//Preventing the count greater than no of elements in the list or count is 0 of less than 0

if (count > list.Count || count <= 0)
{
    //first arguement is the parameter
    //second arguement is the message we want to show
    throw new ArgumentOutOfRangeException("count", "Count should be between 1 and the number of elements in the list");
}


//Preventing a null being thrown as the list
if (list == null)
{
    throw new ArgumentNullException("list");
}

Different type of access modifier: private, public, protected and internal. Link

Last updated