Yaniv Bialik C Sharp .NET - סיכום FULLSTACK קורס Table of Contents C# Language Fundamentals ........................................................................................................................................5 Control Statements ..................................................................................................................................................... 6 o If-Else ....................................................................................................................................................................... 6 o While ....................................................................................................................................................................... 6 o Do-While ................................................................................................................................................................ 6 o For ........................................................................................................................................................................... 6 o Foreach.................................................................................................................................................................... 6 o Switch ...................................................................................................................................................................... 6 Type Members ...........................................................................................................................................................7 Types may contain: ..................................................................................................................................................... 7 o Fields ....................................................................................................................................................................... 7 o Methods .................................................................................................................................................................. 7 o Constructors ............................................................................................................................................................ 7 o Accessibility Modifiers ............................................................................................................................................ 7 o Properties ................................................................................................................................................................ 8 o Static Member......................................................................................................................................................... 9 o Static Methods ........................................................................................................................................................ 9 o Static Constructor ................................................................................................................................................. 10 o Static Classes ......................................................................................................................................................... 10 o Const Fields ........................................................................................................................................................... 10 o Readonly Fields ..................................................................................................................................................... 10 o Enumerated Data Types ........................................................................................................................................ 11 Encapsulation ............................................................................................................................................................ 11 o Encapsulation Best Practices ................................................................................................................................ 11 Arrays, Collections and Strings ................................................................................................................................. 12 Arrays ........................................................................................................................................................................ 12 o Creating Arrays...................................................................................................................................................... 12 o Initializing Arrays ................................................................................................................................................... 12 o Accessing Arrays.................................................................................................................................................... 12 o Multi-Dimensional Arrays ..................................................................................................................................... 13 Strings........................................................................................................................................................................ 13 o Dynamic Strings..................................................................................................................................................... 13 Common String Methods .......................................................................................................................................... 14 Collections ................................................................................................................................................................. 15 Inheritance & Polymorphism .................................................................................................................................... 15 Inheritance ................................................................................................................................................................ 15 Derived Constructor Example ................................................................................................................................... 16 Base ........................................................................................................................................................................... 16 Abstract Class ............................................................................................................................................................ 17 Abstract Methods ..................................................................................................................................................... 17 Interfaces .................................................................................................................................................................. 18 Protected Modifier.................................................................................................................................................... 19 Invoking Base Class Functionality ............................................................................................................................. 19 Interface Polymorphism............................................................................................................................................ 19 Casting ....................................................................................................................................................................... 20 o Check before Downcasting ................................................................................................................................... 20 The as Operator ........................................................................................................................................................ 20 Sealed Classes & Methods ........................................................................................................................................ 21 OPP Best Practices .................................................................................................................................................... 21 How Polymorphic Members Work............................................................................................................................ 21 How Shadowing Works ............................................................................................................................................. 22 The Object Class ........................................................................................................................................................ 22 Multiple Interfaces .................................................................................................................................................... 22 Explicit Method Implementation .............................................................................................................................. 23 (Some) Well Known Interfaces.................................................................................................................................. 23 Summary ................................................................................................................................................................... 23 Exceptions ............................................................................................................................................................... 24 Eexception handling .................................................................................................................................................. 24 Throwing Exceptions ................................................................................................................................................. 24 Exception Class.......................................................................................................................................................... 25 o Creating Your Own Exception Types ..................................................................................................................... 25 Best Practices ............................................................................................................................................................ 25 Common Exception Types......................................................................................................................................... 25 Generics .................................................................................................................................................................. 26 Introduction .............................................................................................................................................................. 26 The Need for Generics .............................................................................................................................................. 26 The Need for Generics .............................................................................................................................................. 26 Generic Constructs .................................................................................................................................................... 26 Type Parameters ....................................................................................................................................................... 27 o Open Types and Closed Types .............................................................................................................................. 27 Generic Methods ...................................................................................................................................................... 27 Generic Collections ................................................................................................................................................... 28 o Generic Collections Details ................................................................................................................................... 28 Generic Interfaces ..................................................................................................................................................... 29 Constraints ................................................................................................................................................................ 30 o Constraints Rules .................................................................................................................................................. 30 Nullable Types ........................................................................................................................................................... 30 Singleton ................................................................................................................................................................. 31 What is Singleton Design Pattern?............................................................................................................................ 31 Advantages of Singleton Design Pattern................................................................................................................... 31 Disadvantages of Singleton Design Pattern .............................................................................................................. 31 Singleton class vs. Static methods ............................................................................................................................ 31 Dependency Injection .............................................................................................................................................. 32 Types of Dependency Injection ................................................................................................................................. 33 Constructor Injection ................................................................................................................................................ 33 o Property Injection ..................................................................................................................................................... 34 o Example: Constructor Injection - C# ..................................................................................................................... 33 Example: Property Injection - C# .......................................................................................................................... 34 Method Injection ...................................................................................................................................................... 35 o Example: Interface Injection - C# .......................................................................................................................... 35 ILogger .................................................................................................................................................................. 36 Introduction .............................................................................................................................................................. 36 ILogger vs ILoggerProvider vs IloggerFactory ........................................................................................................... 36 o ILogger................................................................................................................................................................... 36 o ILoggerProvider ..................................................................................................................................................... 36 o ILoggerFactory....................................................................................................................................................... 36 IloggerFactory ........................................................................................................................................................... 37 IloggerFactory ........................................................................................................................................................... 37 ILogger....................................................................................................................................................................... 37 Console Logging Provider .......................................................................................................................................... 38 Log Levels .................................................................................................................................................................. 38 C# Language Fundamentals Control Statements o If-Else if (boolean_expression) Statement; else // optional Statement; o While while (boolean_expression) Statement; o Do-While Do { Statement; } while (boolean_expression); o For for(Init_ expression; boolean_expression; update_ expression) { Statement; } o Foreach foreach(SomeType item in collection) Statement; o Switch string desc; switch(level) { case 0: desc = "very low"; break; case 1: case 2: desc = "medium"; break; default: desc = "high"; break; } Type Members Types may contain: o Fields Represent an object state public class Account { private decimal _balance; private string _name; } o Methods Operations the object can perform public class Account { private decimal balance; private string name; public void Deposit(decimal amount) { balance += amount; } public void Withdraw(decimal amount) { if(balance >= amount) balance -= amount; }} o Constructors A special method called when an instance is created initialize new objects public class Account { private decimal _balance; private string _name; public Account(string name, decimal initial) { _name = name; _balance = initial; } o Accessibility Modifiers o Properties A property provides field-like access to a getter and/or setter methods The set accessor accepts a parameter called value (typed as the property type) public struct Point { private double _x; private double _y; public double X { get { return _x; } set { _x = value; } } public double Y { get { return _y; } set { _y = value; } } } Point p1 = new Point(); p1.X = 4; p1.Y = p1.X * 2; Console.WriteLine("({0},{1} )", p1.X, p1.Y); A property does not have to wrap a field The set block can do validation The get block can return some computed value not available directly public class Car { private bool _asMph; public bool AsMph { get { return _asMph; } set { _asMph = value; } } public int _speed; public int Speed { get { int result = _speed; if(AsMph) result = result * 5 / 8; return result; } private set { _speed = value; } } public void Accelerate(int weight) { Speed += weight; } } Car car = new Car(); car.Accelerate(10); car.Accelerate(25); car.Accelerate(40); Console.WriteLine($"Speed (KPH): {car.Speed}"); car.AsMph = true; Console.WriteLine($"Speed (MPH): {car.Speed}"); o Static Member Belong to the type, not to instances Only one copy, regardless of instances public class Account { private decimal _balance; private string _name; private int _id; private static int _globalid = 1; internal static int NextAccountID { get { return _globalid; } } } Console.WriteLine($"Next Account ID: {Account.NextAccountID}") o Static Methods Can access other static members Cannot access instance members public class Account { private decimal _balance; private string _name; private int _id; private static int _globalid = 1; internal static int NextAccountID { get { return _globalid; } } public string Name { get { return _name; } } public decimal Balance { get { return _balance; } } public static Account CreateAccount(string name) { Account acc = new Account(name); acc.Deposit(10); // complementary! return acc; } //... private Account(string name) { _name = name; _id = _globalid++;}} Account acc = Account.CreateAccount("John"); Console.WriteLine($"Account {acc.Name} has ${acc.Balance}"); o Static Constructor Used to initialize static fields with dynamic information static Account() { StreamReader reader = new StreamReader(@"c:\MyApp\config.txt"); int.TryParse(reader.ReadLine(), out _globalid); reader.Close();} o Static Classes Can contain static members only Used to logically group related methods public static class AccountFactory { public static Account CreateAccount(string name) { Account acc = new Account(name); acc.Deposit(10); return acc; }} Account acc = AccountFactory.CreateAccount("John"); Console.WriteLine($"Account {acc.Name} has ${acc.Balance}"); o Const Fields A const field is implicitly static public class Account { public const int MaxAccountsPerName = 5; o Readonly Fields Readonly indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class public class Account { public const int MaxAccountsPerName = 5; private decimal _balance; private readonly string _name; private readonly int _id; public readonly DateTime AccountCreated = DateTime.Now; private Account(string name) { _name = name; _id = _globalid++; } o Enumerated Data Types Integral user defined type Numeric values represented by named constants public enum CardSuit { Spades, Diamonds, Hearts, Clubs } public enum CardFace { Ace = 1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack = Ten, Queen = Ten, King = Ten} public class Card { public CardFace Face { get; private set; } public CardSuit Suit { get; private set; } public Card(CardSuit suit, CardFace face) { Suit = suit; Face = face; } public void Display() { Console.WriteLine("{0} of {1}", Face, Suit); }} Encapsulation defined as the process of enclosing one or more items within a physical or logical package'. prevents access to implementation details. o Encapsulation Best Practices Fields should be private Properties should allow setting in any order before first methods invocation Internal types are “helper” or “implementation” types not visible outside the assembly Methods should be used to significantly change the object’s state Arrays, Collections and Strings Arrays Array is an ordered collection of values of the same type o Creating Arrays Declare a variable of an array type int[] numbers; Account[] bankAccounts; Create the array instance numbers = new int[10]; bankAccounts = new Account[6]; o Initializing Arrays Can initialize an array while declaring int[] numbers = { 3, 44, 11, 0, -7 }; Account[] bankAccounts = { // 6 accounts new Account("Homer"), null, new Account("Bart"), new Account("Lisa"), null, new Account("Marge") }; o Accessing Arrays Elements accessed using the [] operator Can iterate through an array with foreach foreach(Account ac in bankAccounts) if(ac != null) ac.Deposit(50); Can use the Length property for(int i = 0; i < numbers.Length; i++) numbers[i] = rnd.Next(1, 100); o Multi-Dimensional Arrays Arrays can have more than one dimension double[,] matrix = new double[10, 10]; string[,] data = new string[,] { // 2 x 3 { "New york", "Paris", "London" }, { "USA", "France", "United Kingdom" }}; Can use nested loops to access/fill array for(int i = 0; i < matrix.GetLength(0); i++) for(int j = 0; j < matrix.GetLength(1); j++) matrix[i, j] = (i + 1) * (j + 1); Strings Collection of Unicode characters Immutable o Dynamic Strings System.Text.StringBuilder A dynamic (expandable) string Call Append or AppendLine to extend string Call ToString to get a regular String object string hello = "Hello, world!"; StringBuilder sb = new StringBuilder(); sb.Append("This is a ").AppendLine("A dynamic string!").AppendLine(hello); Console.WriteLine(sb.ToString()); string s1 = "x"; Stopwatch sw = Stopwatch.StartNew(); for(int i = 0; i < 100000; i++) s1 += "x"; sw.Stop(); Console.WriteLine($"Concatenation with strings: {sw.ElapsedMilliseconds}"); sw.Reset(); sw.Start(); StringBuilder s2 = new StringBuilder("x"); for(int i = 0; i < 100000; i++) s2.Append("x"); sw.Stop(); Console.WriteLine($"Concatenation with StringBuilder: {sw.ElapsedMilliseconds}") Common String Methods Collections The System.Collections namespace hosts types that implement alternate ways to manage collections of objects ArrayList – dynamic array Stack – LIFO data structure Queue – FIFO data structure Hashtable – fast lookup by key Inheritance & Polymorphism Inheritance Is inheritance, the ability to create classes which inherits certain aspects from parent classes. public class Animal { public void Greet() { Console.WriteLine("Hello, I'm some sort of animal!"); }} // Dog Inherits from Animal base classs public class Dog : Animal { } Then we can Create a new Animal and a new Dog. They will both have access to the Greet method though Inheritance. Animal animal = new Animal(); animal.Greet(); Dog dog = new Dog(); dog.Greet(); Derived Constructor Example public class Shape { private Color _color; private Point _position; public Shape(Color color, Point pos) { _color = color; _position = pos; } } public class Rectangle : Shape { private double _width; private double _height; public Rectangle(Color color, Point pos, double width, double height) : base(color, pos) { _width = width; _height = height; } public Rectangle(Point pos, double width, double height) : this(Color.Black, pos, width, height) { } } Base Inherited method, even when you override it, using the base keyword. public override void Greet() { you can still access the base class by using the base keyword } base.Greet(); Console.WriteLine("Yes I am - a dog!"); Abstract Class Abstract classes, marked by the keyword abstract in the class definition, are typically used to define a base class in the hierarchy You can't create an instance of them. // We can't new up an abstract class abstract class FourLeggedAnimal { public virtual string Describe() { return "Not much is known about this four legged animal!"; } } // We can inherit from it ! class Dog : FourLeggedAnimal {} Abstract Methods Abstract methods are only allowed within abstract classes. We define them as abstract but without any code Then in our inherited class we override that method description abstract class FourLeggedAnimal { /* Define the abstract method definition from within the abstract class */ public abstract string Describe(); } class Dog : FourLeggedAnimal { /* Override the abstract method definition from within the sub class and add code block */ public override string Describe() { return "I'm a dog!"; }} Interfaces Interfaces are similar to Abstract Classes No Instances are created. NO METHODS ARE ALLOWED AT ALL All Interfaces are Public There are NO access modifiers (public, private, protected etc.), because they are not allowed. You can implement as many interfaces as you want to into a single class IXxxx naming convention also helps identify interface types class Program { static void Main(string[] args) { List<Dog> dogs = new List<Dog>(); dogs.Add(new Dog("Fido")); dogs.Add(new Dog("Bob")); dogs.Add(new Dog("Adam")); dogs.Sort(); foreach(Dog dog in dogs) Console.WriteLine(dog.Describe()); Console.ReadKey(); } } interface IAnimal { string Describe(); string Name { get; set; } } class Dog : IAnimal, IComparable { private string name; public Dog(string name) { this.Name = name; } public string Describe() { return "Hello, I'm a dog and my name is " + this.Name; } // This method comes from the IComparable interface public int CompareTo(object obj) { if(obj is IAnimal) return this.Name.CompareTo((obj as IAnimal).Name); return 0; } public string Name { get { return name; } set { name = value; } } } Protected Modifier Modifier that allows access to deriving types only Used to restrict access to methods and properties Fields should always be private public class Form : xxx { protected virtual void OnClosing(CancelEventArgs e) { // raises ‘Closing’ event } } public class MyForm : Form { protected override void OnClosing(CancelEventArgs e) { // do something else first // call the base class' method potentially } }} Whichever ‘hidden’ code is calling this method Polymorphically invokes this one (yours) instead Invoking Base Class Functionality A derived class can access base class members Avoids code duplication and access to private fields To call a base class member, use the base referenc Calls first member with matching signature higher up the inheritance hierarchy public class MyForm : Form { protected override void OnClosing(CancelEventArgs e) { // do something else first // call the base class' method potentially } } } Interface Polymorphism An interface defines a new type, just like a class If a method has parameter of an interface type, it can be passed a reference to an object of any class that implements the interface Can also have collections of objects that implement a specific interface public class Canvas { private ArrayList shapes; } Only stores ‘object’ refs private void RenderRenderables() { foreach(Shape s in shapes) { if(s is IRenderable) ((IRenderable)s).Draw(); } } Implicit cast from Object to Shape Casting An object of a derived class can be treated as an object of a base class without explicit casting (upcasting) Base type variable needs to be explicitly cast to use as a derived type Known as a down cast public class Shape {... } public class Ellipse : Shape {... } Shape s = s.Draw(); Ellipse e float f = GetShapeFromPoint(); // defined in Shape = (Ellipse) s; e.Circumference; // defined in Ellipse o Check before Downcasting If the object is not an object of the derived class System.InvalidCastException is thrown The operator is enables type checking ... public float GetCircumference( Shape s ) { float result = 0.0f; if( s is Ellipse ) { Ellipse e = (Ellipse) s; result = e.Circumference; } return result; } The as Operator The operator as works like a cast except An exception won't be thrown null is returned if the cast doesn't work Slightly more efficient than a check with is public float GetCircumference( Shape s ) { float result = 0.0f; Ellipse e = s as Ellipse; if( e != null ) { result = e.Circumference; } return result; } Sealed Classes & Methods A class can be written with the sealed modifier Prevents it from being extended An override method can be sealed override The String class is seales All structs & enums are automatically sealed public sealed class Color { ... } OPP Best Practices Use inheritance only for genuine "is a" relationships Logical to sub object of derived class with object of base class All methods in base class should make sense in derived class Ad-hoc inheritance for short-term convenience tends to lead to future problems and surprises! The CLR only supports single inheritance Choosing a base class is thus significant in lots of ways How Polymorphic Members Work How Shadowing Works The Object Class System.Object defines methods inherited by all types Equals, GetHashCode, GetType, ToString Derived classes override as necessary System.Object.Equals - Compares references System.String.Equals - Compares values System.ValueType.Equals - Compares values Should override GetHashCode and Equals as a pair Two equal objects should return the same hash code Multiple Interfaces A class can implement multiple interfaces You do not inherit from an interface, you implement it public interface IComparable { int CompareTo(object o1); } public interface IRenderable { void Draw(); } public class Rectangle : IComparable, IRenderable { private int height, width; public void Draw() { ... } public int CompareTo( object o1 ) { Rectangle r = o1 as Rectangle; return ... }} Explicit Method Implementation A class can provide an explicit implementation Defined with the interface name, but without an access modifier It is implicitly public through an interface reference And implicitly private through a class reference (Some) Well Known Interfaces Summary An abstract class cannot be instantiated Represents a generalisation of some concept May contain abstract methods An abstract member has a signature, but no code To be implemented by derived classes An interface is a collection of abstract methods To be implemented by a class that implements the interface A class can implement more than one interface Provides many of the benefits of multiple inheritances Abstract classes and interfaces are both polymorphic Exceptions Eexception handling .NET uses exception handling Code tries to perform a task, if it fails an exception is thrown Exceptions can then be caught and handled SqlConnection con = new SqlConnection( ... ); try { con.Open(); code that may throw an exception ... ... } catch( SqlException exn ) { Console.WriteLine("Data access error: " + exn.Message); Clean up and/or abort } catch( Exception exn ) { Console.WriteLine("General error: " + exn.Message); } finally { con.Close(); Execute this whatever happens } //remainder of containing method ... Throwing Exceptions To 'raise' an exception, we throw it Pass information through constructor arguments void PrintReport( Report rpt ) { if( rpt == null ) { throw new ArgumentNullException( "rpt", "Can't print a null report"); } catch( ArgumentNullException exn ){ ... } ... throw; } You can re-throw a caught exception This maintains original stack location where exception thrown Can rethrow a different (higher level) exception Exception Class Base class of exception classes Provides properties Message – textual description of error StackTrace – the trace of methods that lead to the exception InnerException – wrapped exception in a re-throw scenario And constructors Empty Accepting a string (initializes Message) Accepting a string and an inner exception o Creating Your Own Exception Types Must derive the class from System.Exception Or another specific exception Duplicate the constructors and pass up to the base class [Serializable] public class MyException : Exception { public MyException( string m ) : base( m ) {…} // and other overloaded constructors/fields/methods } To provide rich exception information Overload the constructor to pass in details Provide public property accessors to allow retrieval Override ToString to display neatly Best Practices Don't catch System.Exception Don't try to catch every possible exception type You don't need try {} catch {} in every method Use finally blocks to ensure resources are freed Test your code in your exception handlers Common Exception Types System.StackOverflowException System.NullReferenceException System.TypeInitializationException System.InvalidCastException System.ArrayTypeMismatchException System.IndexOutOfRangeException System.DivideByZeroException System.OverflowException Generics Introduction Generics introduce the concept of type parameters to .NET, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code The Need for Generics using System; using System.Collections.Generic; public class WithGenerics { public static void Main() { List<DateTime> list = new List<DateTime>(); list.Add(DateTime.Now); list.Add(5); list.Add("Hello"); DateTime now = list[0]; // no boxing // compilation error // ditto // no unboxing } } The Need for Generics Performance Reduce boxing / unboxing Fewer downcasts Type safety Compile time vs. run time Generic algorithms Sorting, searching, etc. Increased code re-use Type independent code, such as collections Generic Constructs The following can be made generic: Classes public class List<T> { ... } Structures public struct Container<T> { ... } Interfaces public interface IComparable<T> { ... } Delegates public delegate void EventHandler<T>( object sender, T e ); Methods public T Foo<T>() { ... } Type Parameters Type parameter can be used in place of fixed types public class Stack<T> : IEnumerable<T> { private List<T> dataItems = new List<T>(); public void Push(T item) { dataItems.Insert(0, item); } public T Pop() { T retVal = dataItems[0]; dataItems.RemoveAt(0); return retVal; } } Types and Closed Types o Open A generic type is called an open type No instance can be created When specifying specific types when using a generic type, it becomes a closed type Can be instantiated Static fields are per closed type Static constructors execute once per closed type Generic Methods A method can be genericised Even in a type which is not itself generic Generic types sometimes don’t have to be provided The compiler can infer the types public static class ArrayFactory { public static T[] CreateArray<T>(int size) { return new T[size]; } } string[] towns = ArrayFactory.CreateArray<string>(20); Generic Collections Generic collection classes exist in the System.Collections.Generic namespace Replacing Object-based collections in previous versions o Generic Collections Details List<T> A dynamic array Always prefer this class if no other special requirements exist Stack<T> Queue<T> A Last in first out (LIFO) collection A first in first out (FIFO) collection Dictionary<K, V> A hashtable where keys must be unique Searches are O(1) Hash value queried with K.GetHashCode() SortedList<K,V> and SortedDictionary<K,V> Maintain a sorted list of values based on IComparable<K> (see later) Retrieval of values at O(log n) SortedDictionary<> is a binary search tree SortedList<> uses less memory SortedDictionary<> has faster insert and remove for unsorted data (O(log n) vs. O(n)) SortedList<> has efficient indexed retrieval from the Keys and Values properties LinkedList<T> Doubly linked list Insertion and removal is an O(1) operation Implements the ICollection<T> interface HashSet<T> A set of values that must be unique Starting from .NET 4, implements the ISet<T> interface Retrieval is an O(1) operation SortedSet<T> Similar to a HashSet<>, but keeps values sorted Generic Interfaces IEnumerable<T> Indicates a collection class Can be iterated with the foreach statement public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); } IEnumerator<T> Implemented by an iterator Typically returned by IEnumerable<T>.GetEnumerator public interface IEnumerator<out T> : IDisposable, IEnumerator { T Current { get; } } ICollection<T> Some inherit the non-generic interfaces Object is replaced by the a generic parameter Implemented by collections that support adding and removing of items public interface ICollection<T> : IEnumerable<T>, IEnumerable { int Count { get; } bool IsReadOnly { get; } void Add(T item); void Clear(); public interface IList<T> : ICollec bool Contains(T item); tion<T>, void CopyTo(T[] array, int index); IEnumerable<T>, IEnumerable { IList<T> bool Remove(T item); T this[int index] { get; set; } int IndexOf(T item); Inherits from ICollection<T> void Insert(int index, T item); void RemoveAt(int index); Adds indexing capabilities } IComparable<T> Implemented by a type that can compare itself to another instance One method only: CompareTo Must return greater than zero if (this) is greater, less than zero if smaller, or zero if equal Useful in sorting scenarios IComparer<T> Implemented by a custom comparer Useful for customizing sorting criteria public interface IComparable<in T> { int CompareTo(T other); } public interface IComparer<in T> { int Compare(T x, T y); } Constraints A way to limit the type replacements for generic arguments Base type Supported interfaces Public default constructor Use the where keyword for base type and interfaces, the new keyword for default constructor public static T Min<T>(T o1, T o2) where T IComparable<T> { if(o1.CompareTo(o2) < 0) return o1; return o2; } public class ShapeDictionary<Key, Val> where Key : IComparable<Key> where Val : Shape, new() { } o Constraints Rules Order of constraints Base type (one at most), interfaces (as many as required), default constructor Can’t overload based on different constraints or by adding constraints When overriding a generic virtual method, type arguments must be the same Constraints are inherited automatically Base type cannot be Object, Void, Delegate, MulticastDelegate, ValueType, Enum, Array Special base types class: any reference type struct: any value type Use default(T) to set default value (0, null or false) Comparing a generic parameter with null is always allowed Operator overloading is not allowed on generic types No constraints exist for this Nullable Types System.Nullable<T> Represents value type of type T or null Contains two properties HasValue Boolean signifying whether object actually contains a valid value Value The actual value (of type T) Singleton What is Singleton Design Pattern? Singleton design pattern in C# is one of the most popular design pattern. In this pattern, a class has only one instance in the program that provides a global point of access to it. In other words, a singleton is a class that allows only a single instance of itself to be created and usually gives simple access to that instance. There are various ways to implement a singleton pattern in C#. The following are the common characteristics of a singleton pattern. Private and parameterless single constructor Sealed class. Static variable to hold a reference to the single created instance A public and static way of getting the reference to the created instance. Advantages of Singleton Design Pattern The advantages of a Singleton Pattern are, 1. Singleton pattern can implement interfaces. 2. Can be lazy-loaded and has Static Initialization. 3. It helps to hide dependencies. 4. It provides a single point of access to a particular instance, so it is easy to maintain. Disadvantages of Singleton Design Pattern The disadvantages of a Singleton Pattern are, 1. Unit testing is a bit difficult as it introduces a global state into an application 2. Reduces the potential for parallelism within a program by locking. Singleton class vs. Static methods The following compares Singleton class vs. Static methods, 1. A Static Class cannot be extended whereas a singleton class can be extended. 2. A Static Class cannot be initialized whereas a singleton class can be. 3. A Static class is loaded automatically by the CLR when the program containing the class is loaded. Dependency Injection Dependency Injection (DI) is a software design pattern. It allows us to develop loosely-coupled code. The intent of Dependency Injection is to make code maintainable. Dependency Injection helps to reduce the tight coupling among software components. Dependency Injection reduces the hard-coded dependencies among your classes by injecting those dependencies at run time instead of design time technically. This article explains how to implement Dependency Injection in C# and .NET code. The Dependency Injection pattern involves 3 types of classes. 1. Client Class: The client class (dependent class) is a class which depends on the service class 2. Service Class: The service class (dependency) is a class that provides service to the client class. 3. Injector Class: The injector class injects the service class object into the client class. The following figure illustrates the relationship between these classes: Types of Dependency Injection As you have seen above, the injector class injects the service (dependency) to the client (dependent). The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor. Property Injection: In the property injection (aka the Setter Injection), the injector supplies the dependency through a public property of the client class. Method Injection: In this type of injection, the client class implements an interface which declares the method(s) to supply the dependency and the injector uses this interface to supply the dependency to the client class. Constructor Injection o Example: Constructor Injection - C# public class CustomerBusinessLogic { ICustomerDataAccess _dataAccess; public CustomerBusinessLogic(ICustomerDataAccess custDataAccess) { _dataAccess = custDataAccess; } public CustomerBusinessLogic() { _dataAccess = new CustomerDataAccess(); } public string ProcessCustomerData(int id) { return _dataAccess.GetCustomerName(id); } } public interface ICustomerDataAccess { string GetCustomerName(int id); } public class CustomerDataAccess: ICustomerDataAccess { public CustomerDataAccess() { } public string GetCustomerName(int id) { //get the customer name from the db in real application return "Dummy Customer Name"; } } As you can see in the above example, the CustomerService class creates and injects the CustomerDataAccess object into the CustomerBusinessLogic class. Thus, the CustomerBusinessLogic class doesn't need to create an object of CustomerDataAccess using the new keyword or using factory class. The calling class (CustomerService) creates and sets the appropriate DataAccess class to the CustomerBusinessLogic class. In this way, the CustomerBusinessLogic and CustomerDataAccess classes become "more" loosely coupled classes Property Injection o Example: Property Injection - C# public class CustomerBusinessLogic { public CustomerBusinessLogic() { } public string GetCustomerName(int id) { return DataAccess.GetCustomerName(id); } public ICustomerDataAccess DataAccess { get; set; } } public class CustomerService { CustomerBusinessLogic _customerBL; public CustomerService() { _customerBL = new CustomerBusinessLogic(); _customerBL.DataAccess = new CustomerDataAccess(); } public string GetCustomerName(int id) { return _customerBL.GetCustomerName(id); } } As you can see above, the CustomerBusinessLogic class includes the public property named DataAccess, where you can set an instance of a class that implements ICustomerDataAccess. So, CustomerService class creates and sets CustomerDataAccess class using this public property. Method Injection In the method injection, dependencies are provided through methods. This method can be a class method or an interface method. The following example demonstrates the method injection using an interface based method. o Example: Interface Injection - C# interface IDataAccessDependency { void SetDependency(ICustomerDataAccess customerDataAccess); } public class CustomerBusinessLogic : IDataAccessDependency { ICustomerDataAccess _dataAccess; public CustomerBusinessLogic() { } public string GetCustomerName(int id) { return _dataAccess.GetCustomerName(id); } public void SetDependency(ICustomerDataAccess customerDataAccess) { _dataAccess = customerDataAccess; } } public class CustomerService { CustomerBusinessLogic _customerBL; public CustomerService() { _customerBL = new CustomerBusinessLogic(); ((IDataAccessDependency)_customerBL).SetDependency(new CustomerDataAccess()); } public string GetCustomerName(int id) { return _customerBL.GetCustomerName(id); } } In the above example, the CustomerBusinessLogic class implements the IDataAccessDependency interface, which includes the SetDependency() method. So, the injector class CustomerService will now use this method to inject the dependent class (CustomerDataAccess) to the client class. ILogger Introduction The logging interfaces provided by the Microsoft.Extensions.Logging.Abstractions NuGet package provide common logging abstractions with implementations for various logging backends and sinks. Microsoft.Extensions.Logging includes the necessary classes and interfaces for logging. The most important are the ILogger, ILoggerFactory, ILoggerProvider interfaces and the LoggerFactory class. ILogger vs ILoggerProvider vs IloggerFactory o ILogger The responsibility of the ILogger interface is to write a log message of a given log level and create logging scopes. The interface itself only exposes some generic log methods which are then used by “external” extension methods like LogInformation or LogError. o ILoggerProvider A logger provider is an actual logging sink implementation, e.g. console, Application Insights, files or Serilog (an adapter to the Serilog logging abstraction). The ILoggerProvider’s only responsibility is to create ILogger instances which log to an actual sink. A logger instance which is created by a logger provider will only log to the associated logger provider. o ILoggerFactory The ILoggerFactory logger factory instance is the boostrapper of the logging system: It is used to attach logger providers and create logger instances - either typed (ILogger<T>) or untyped (ILogger). These logger instances will log to all registered logger providers. IloggerFactory The ILoggerFactory is the factory interface for creating an appropriate ILogger type instance and also for adding the ILoggerProvider instance. public interface ILoggerFactory : IDisposable { ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider); } The Logging API includes the built-in LoggerFactory class that implements the ILoggerFactory interface. We can use it to add an instance of type ILoggerProvider and to retrieve the ILogger instance for the specified category. Visit ILoggerFactory and LoggerFactory for more information. IloggerFactory The ILoggerProvider manages and creates an appropriate logger, specified by the logging category. public interface ILoggerProvider : IDisposable { ILogger CreateLogger(string categoryName); } ILogger The ILogger interface includes methods for logging to the underlying storage. There are many extension methods which make logging easy. Visit ILogger for more information. public interface ILogger { void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter); bool IsEnabled(LogLevel logLevel); IDisposable BeginScope<TState>(TState state); } Console Logging Provider Log Levels Log levels indicate the importance or severity of log messages. Built-in log providers include extension methods to indicate log levels. The following table lists log levels in .NET Core. We can use extension methods to indicate the level of the log messages as shown below. Files Read File using (var sr = File.OpenText(path)) { string s; while ((s = sr.ReadLine()) != null) Console.WriteLine(s); { } } Write File var path = @"C:\Users\escap\Source\Repos\ConsoleApp1\ConsoleApp1\Main.cs"; if (!File.Exists(path)) using (var sw = File.CreateText(path)) { sw.WriteLine("for (int i = 0; i<length; i++)"); } Serialization Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization. public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new() { TextWriter writer = null; try { var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite); writer = new StreamWriter(filePath, append); writer.Write(contentsToWriteToFile); } finally { if (writer != null) writer.Close(); } } Deserialization public static T ReadFromJsonFile<T>(string filePath) where T : new() { TextReader reader = null; try { reader = new StreamReader(filePath); var fileContents = reader.ReadToEnd(); return JsonConvert.DeserializeObject<T>(fileContents); } finally { if (reader != null) reader.Close(); } } Lambda Expressions Lambda Lambda expressions in C# are used like anonymous functions, with the difference that in Lambda expressions you don’t need to specify the type of the value that you input thus making it more flexible to use. The ‘=>’ is the lambda operator which is used in all lambda expressions. The Lambda expression is divided into two parts, the left side is the input and the right is the expression. The Lambda Expressions can be of two types: Expression Lambda: Consists of the input and the expression. Syntax: input => expression; Statement Lambda: Consists of the input and a set of statements to be executed. Syntax: input => { statements }; Example 1 In the code given below, we have a list of integer numbers. The first lambda expression evaluates every element’s square { x => x*x } and the second is used to find which values are divisible by 3 { x => (x % 3) == 0 }. And the foreach loops are used for displaying. // Using lambda expression // to calculate square of // each value in the list var square = numbers.Select(x => x * x); // Using Lambda expression to // find all numbers in the list // divisible by 3 List<int> divBy3 = numbers.FindAll(x => (x % 3) == 0); Console.Write("Numbers Divisible by 3 : "); foreach(var value in divBy3) { Console.Write("{0} ", value); } Example 2 Lambda expressions can also be used with user-defined classes. The code given below shows how to sort through a list based on an attribute of the class that the list is defined upon. // C# program to illustrate the // Lambda Expression // User defined class Student class Student { // properties rollNo and name public int rollNo { get; set; } public string name { get; set; } } class GFG { // Main Method static void Main(string[] args) { // List with eah element of type Student List<Student> details = new List<Student>() { new Student{ rollNo = 1, name = "Liza" }, new Student{ rollNo = 2, name = "Stewart" }, new Student{ rollNo = 3, name = "Tina" }, new Student{ rollNo = 4, name = "Stefani" }, new Student { rollNo = 5, name = "Trish" } }; // To sort the details list // based on name of student // in acsending order var newDetails = details.OrderBy(x => x.name); foreach(var value in newDetails) { Console.WriteLine(value.rollNo + " " + value.name); } } } Collections List<T> The List<T> is a collection of strongly typed objects that can be accessed by index and having methods for sorting, searching, and modifying list. It is the generic version comes under System.Collection.Generic namespace List<int> primeNumbers = new List<int>(); primeNumbers.Add(1); // adding elements using add() method primeNumbers.Add(3); primeNumbers.Add(5); primeNumbers.Add(7); var cities = new List<string>(); cities.Add("New York"); cities.Add("London"); cities.Add("Mumbai"); cities.Add("Chicago"); cities.Add(null);// nulls are allowed for reference type list //adding elements using collection-initializer syntax var bigCities = new List<string>() { "New York", "London", "Mumbai", "Chicago" }; Dictionary<TKey,TValue> o Dictionary Characteristics Dictionary<TKey, TValue> stores key-value pairs. Comes under System.Collections.Generic namespace. Implements IDictionary<TKey, TValue> interface. Keys must be unique and cannot be null. Values can be null or duplicate. Values can be accessed by passing associated key in the indexer e.g., myDictionary[key] Elements are stored as KeyValuePair<TKey, TValue> objects. o Create Dictionary and Add Elements IDictionary<int, string> numberNames = new Dictionary<int, string>(); numberNames.Add(1,"One"); //adding a key/value using the Add() method numberNames.Add(2,"Two"); numberNames.Add(3,"Three"); //The following throws run-time exception: key already added. //numberNames.Add(3, "Three"); foreach(KeyValuePair<int, string> kvp in numberNames) Console.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value); //creating a dictionary using collection-initializer syntax var cities = new Dictionary<string, string>(){ {"UK", "London, Manchester, Birmingham"}, {"USA", "Chicago, New York, Washington"}, {"India", "Mumbai, New Delhi, Pune"} }; foreach(var kvp in cities) Console.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value); Linq LINQ (Language Integrated Query) is uniform query syntax in C# and VB.NET to retrieve data from different sources and formats. It is integrated in C# or VB, thereby eliminating the mismatch between programming languages and databases, as well as providing a single querying interface for different types of data sources. // Data source string[] names = {"Bill", "Steve", "James", "Mohan" }; // LINQ Query var myLinqQuery = from name in names where name.Contains('a') select name; // Query execution foreach(var name in myLinqQuery) Console.Write(name + " "); h Unit Test Moq Test types Code coverage Devops