C#

Programming Language

Mohammad Dehghan
mohammadhd@systemgroup.net
SystemGroup www.systemgroup.net

C# Programming Language

  • General-purpose, type-safe, object-oriented
  • Supports functional programming
  • Supports dynamic typing
  • Supports declarative programming
  • Supports asynchronous programming

Object Orientation

  • Unified type system
  • Classes and interfaces
  • Methods, properties, events

Type Safety

  • Compile-time static typing
  • Run-time type safety
  • Strongly typed
  • dynamic keyword

Functional Programming

  • Functions as values (delegate)
  • Anonymous methods and lambda expressions
  • Captured local variables

Declarative Programming

  • Language-integrated query (LINQ)
    • Fluent-syntax (Extension methods and lambda expressions)
    • Query-syntax (declarative)

Asynchronous Programming

  • Tasks
  • async/await
  • Memory Management

    • Garbage collector
    • No delete keyword

    .NET Platform

    • Development tools (compiler)
    • Runtime services (CLR)
    • Class library

    .NET Platform Variations

    • .NET Framework
    • .NET Core
    • Mono
    • Xamarin

    Let's do it!

    Creating first application

    • Install .NET Core
    • Open a terminal window
      (PowerShell/Command Prompt/bash)
    • 
                                  $ md HelloCS
                                  $ cd HelloCS
                                  $ dotnet new console
                                  $ dotnet run
                              

    Working With Visual Studio Code

    • Install Visual Studio Code
    • Install C# extension
    • Open project folder
      • Let the C# extension install required files
      • VS Code prompts you about adding required assets to build and debug. Click "Yes".

    Analyzing the program

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

    Main Method

    • Starting point of an executable
    • Passing command line arguments

    Namespaces

    • Namespaces organize types
    • Avoid type name collisions
    • using directive brings other namespaces’ types into scope
    • Type full name

    Types

    • C# is strongly typed
    • Everything has a type
    • We can define our own types
    • Code you want to execute must live inside a type

    Statements and Expressions

    • A statement is an instruction
      • A method is a series of instructions
      • Statements end with semicolon
      • Statements are executed in order they appear
    • Expressions are parts of statements that produce a value
      • The may involve operators

    Objects

    • Everything is an object
    • Objects have members
    • Members are accessed by dot (.) operator

    Variables

    Variables hold a value
    • They always have a type
    • They must be assigned a value before they can be used
    • Variable’s type usually determines how much memory it consumes
                        
                            int i;
                            float x, y;
                            string name = "Mohammad";
                        
                    

    Numeric Types (Part One)

    Integers
    • Signed (int, long, short, sbyte)
    • Unsigned (uint, ulong, ushort, byte)
     
                            byte b = 30;
                            int i = 12000 + b;
                            i = 10 / 3;
                            short s = 762190; // Error: Constant value '762190'
                                              // cannot be converted to a 'short'
                        

    Numeric Types (Part Two)

    Real numbers
    • Floating point (float, double)
      • Typically used for scientific and graphical calculations
    • Decimal (decimal)
      • Typically used for financial calculations, where base-10-accurate arithmetic and high precision are required
    
                            double pi = 3.1415926535897932384; // 3.14159265358979
                            float fpi = (float)pi;             // 3.141593
                            double x = 10 / 3;                 // 3!
                        

    Numeric Literals

    
                            int million = 1_000_000; // underscore can be
                                                     // inserted anywhere (C# 7)
                            int x = 0x7f;            // 0x prefix: hexadecimal literal
                            byte b = 0b10000000;     // 0b prefix: binary literal (C# 7)
                            byte b2 = 0b1000_1000;
                            double d = 1.5;
                            double million2 = 1e06;
                            float f = 1.2f;
                            decimal dec = -1.23M;    // Will not compile without the M suffix.
                        

    Numeric Conversions

    
                            int x = 12345;      // int is a 32-bit integer
                            long y = x;         // Implicit conversion to 64-bit integral type
                            short z = (short)x; // Explicit conversion to 16-bit integral type
    
                            int i = 10;
                            decimal d = i;
                            int j = (int)d;
    
                            i = (int)1.7;   // 1 - fractional portion is truncated
                            float f = 1.1f;
                            d = (decimal)f;
                            double d2 = (double)d;
                        

    Arithmetic Operators

    + Addition
    - Subtraction
    * Multiplication
    / Division
    % Remainder after division
    ++ Increment
    -- Decrement

    Skipped: overflow and check operators, bitwise operators

    Pre/Post Increment/Decrement

    
                            int x = 0, y = 0;
                            Console.WriteLine (x++); // Outputs 0; x is now 1
                            Console.WriteLine (++y); // Outputs 1; y is now 1
                        

    Boolean

    • true or false
    • Result of relational operators
    
                        float temperature = 20;
                        bool isHot = temperature > 35;
    
                        bool rainy = true;
                        bool sunny = false;
                        bool windy = true;
                        bool useUmbrella  = !windy && (rainy || sunny);
                    

    Characters

    • Characters are Unicode
    • Escape sequences
      
                                          char newLine = '\n';
                                          char backSlash = '\\'
                                      

    Strings

    
                            string a = "Here's a tab:\t";
                            string a1 = "\\\\server\\fileshare\\helloworld.cs";
                            // Verbatim string literal
                            string a2 = @"\\server\fileshare\helloworld.cs";
                            int l = s2.Length;
                        

    String interpolation (C# 6)

    
                                int x = 4;
                                Console.Write ($"A square has {x} sides");
                            

    String Operators

    • Concatenation (+)
    • Equality (==)
    • Indexer ([])
    • Instance and static methods (CompareTo, Split, Substring, ...)

    C# Built-In Types Summary

    • Value types
      • Numeric
        • Signed integer (sbyte, short, int, long)
        • Unsigned integer (byte, ushort, uint, ulong)
        • Real number (float, double, decimal)
      • Logical (bool)
      • Character (char)
    • Reference types
      • String (string)
      • Object (object)
    • Primitive types: Predefined values types except decimal

    C# Built-In Types

    C# Type .NET Framework Type C# Type .NET Framework Type
    bool System.Boolean unit System.UInt32
    byte System.Byte long System.Int64
    sbyte System.SByte ulong System.UInt64
    char System.Char object System.Object
    decimal System.Decimal short System.Int16
    double System.Double ushort System.UInt16
    float System.Single string System.String
    int System.Int32    

    Control Statements

    • if/else
    • switch
      • Only numbers, characters, strings and booleans
      • case labels are constants
      • default label is optional
      • Cannot fall through another case, unless it has no statements
      • goto case / goto default
      Conditional expression (?:)

    Arrays

    Multiple variables under the same name

    • Accessible through index
    • Index starts from zero
    • All element have the same type
    • new is used to create an array
    • Length property
    • May have more than one dimension
      • Length property gives the total length.
      • GetLength(<dimension>)
    • May be jagged

    Array Initialization

    
                            char[] vowels;        // Declare an array of characters
                            vowels = new char[5]; // Initialize with an array of 5 characters
                
                            // Fill with values
                            vowels[0] = 'a';
                            vowels[1] = 'e';
                            vowels[2] = 'i';
                            vowels[3] = 'o';
                            vowels[4] = 'u';
                        

    Array Initialization

    
                            char[] vowels;
                            vowels = new char[] { 'a', 'e', 'i', 'o', 'u' };
                        
    or
    
                                char[] vowels;
                                vowels = new [] { 'a', 'e', 'i', 'o', 'u' };
                        
    or
    
                            char[] vowels = {'a','e','i','o','u'};
                        

    Array Initialization

    
                            int[,] matrix = 
                            {
                                {0,1,2},
                                {3,4,5},
                                {6,7,8}
                            };
                        
    
                            int[][] matrix = new int[][]
                            {
                                new int[] {0,1,2},
                                new int[] {3,4,5},
                                new int[] {6,7,8,9}
                            };
                        

    Methods - Basics

    • Methods define operations and behaviors
    • Every method has a return type
      • void if no return value
      • return is used to exit the method and/or return a value
      • Multiple return statements are allowed
    • Every method has zero or more parameters
    • Methods can be called recursively
    • Variables defined inside a method are called local variables
    • Methods can be overloaded

    Method Overloads

    
                            static float CalculateWeight(float mass, float gravity)
                            {
                                return mass * gravity;
                            }
                    
                            static float CalculateWeight(float mass)
                            {
                                return CalculateWeight(mass, 9.807f);
                            }
    
                            static void Main()
                            {
                                float mass = 10;
                                float weightOnEarth = CalculateWeight(mass);
                                float weightOnMars = CalculateWeight(mass, 3.711f);
                            }
                        

    Methods Parameters

    • They are local to the method
    • By default, method parameters are "pass by value"
    • Can be optional (by having a default value)
    • ref modifier: "pass by reference" - in/out parameter
    • out modifier: output parameter (also "pass by reference")

    Optional Parameters

    
                            static void Main()
                            {
                                float mass = 10;
                                float weightOnEarth = CalculateWeight(mass);
                                float weightOnMars = CalculateWeight(mass, 3.711f);
                            }
                    
                            static float CalculateWeight(float mass, float gravity = 9.807f)
                            {
                                return mass * gravity;
                            }
                        

    Named Arguments

    
                            void Foo(int x, int y)
                            {
                                Console.WriteLine(x + ", " + y);
                            }
                    
                            void Test()
                            {
                                Foo(x: 1, y: 2); // 1, 2
                                Foo(y: 2, x: 1); // 1, 2
                            }
                        

    The ref Modifier

    
                            static void Foo(ref int p)
                            {
                                p = p + 1; // Increment p by 1
                                Console.WriteLine(p); // Write p to screen
                            }
    
                            static void Main()
                            {
                                int x = 8;
                                Foo(ref x); // Ask Foo to deal directly with x
                                Console.WriteLine(x); // x is now 9
                            }
                        

    The ref Modifier

    
                            static void Swap(ref string a, ref string b)
                            {
                                string temp = a;
                                a = b;
                                b = temp;
                            } 
                        

    The out Modifier

    Like ref modifier, but:
    • Need not be assigned before going into the function
    • Must be assigned before it comes out of the function
    
                            Console.WriteLine("Please enter an integer:");
                            int number;
                            while(true)
                            {
                                string s = Console.ReadLine();
                                if(int.TryParse(s, out number))
                                    break;
                                Console.WriteLine("Not a valid number! Try again:");
                            }
                        

    Out Variable Declaration (C# 7)

    
                            if(double.TryParse(str, out double d))
                            {
                                // do something
                            }
                        

    Out Discards (C# 7)

    
                            static bool IsDateValid(string dateString)
                            {
                                return DateTime.TryParse(dateString, out _);
                            }
                        

    Implicitly Typed Local Variable

    • var keyword
    • Must be assigned a value on declaration
    • Statically typed
    • They are mandatory when using anonymous types
    
                            var i = 10;
                            i = 1.1; // Error: Cannot implicitly convert type 'double' to 'int'.
    
                            var text = Console.ReadLine();
                            var words = text.Split();
    
                            var n;             // Error!
                            var x = 1, y = 10; // Error!
                        

    The params Modifier

    
                            static int Sum(params int[] ints)
                            {
                                int sum = 0;
                                for (int i = 0; i < ints.Length; i++)
                                    sum += ints[i]; // Increase sum by ints[i]
                                return sum;
                            }
                            static void Main()
                            {
                                int total = Sum(1, 2, 3, 4);
                                Console.WriteLine(total); // 10
                            }
                        
    • Allows methods to accept any number of arguments
    • Must be defined as an array
    • Must be the last parameter

    Local Variable Scope

    • Local variables are accessible after definition
    • Every code block defines a scope for local variables
    • Local variables defined in outer scope are accessible in inner scope
    • A variable cannot be defined with the same name as another local variable in outer scope
    
                            static void Main(string[] args)
                            {
                                int a = 1;
                             
                                {
                                    int x = 10, y = 5;
                                    Console.WriteLine(x + " " + y);
                             
                                    int a;          // Error. Already defined in outer scope
                                }
                             
                                {
                                    int x = 30;            // Valid.
                                    Console.WriteLine(a);  // Valid.
                                    Console.WriteLine(x);  // Valid.
                                    Console.WriteLine(y);  // Error. Not accessible
                                }
                            }
                        

    Jumping Statements

    • break
    • continue
    • goto
    • return
    • throw

    Creating Types

    Class

    Creating a new Type:
    
                                class <class_name>
                                {
                                    // state and behavior
                                }
                            

    Class

    • A class is one kind of a type
    • A class groups variables and operations
    • A class defines what an object looks like
    • Objects are instances of a class
    • Every method must be inside of a class
    • Assess modifiers control the visibility of members of class from outside
    • Objects are created with new operator

    Class Members

    • Fields: state of the object
    • Methods: operations of the objects
    • Properties: state accessors
    • Constructors: type initializers - ensure objects are created in a valid state
    • Constants: named values
    • Deconstructors (C# 7): extract state into values
    • Events, Indexers, Operators, Finalizers and Nested Types

    Encapsulation

    • Access modifiers help us achieve encapsulation
    • Hiding internal implementation details:
      • Simplifies usage: others only see what they can use
      • Prevents others from making mistakes: they cannot use what they should not
      • Avoids corruption: by controlling access to internals
      • Makes changes easier: Internal implementation can be changed without affecting others

    Access Modifiers

    • public: everyone from outside can see and use the member
    • private: no access from outside
    • protected: only access from subclasses
    • internal: only access from inside of the assembly
    • protected internal: access from subclasses and others from inside of the assembly
    • private protected(C# 7.2) : access from subclasses within the assembly

    Fields and Properties

    • Variables defined in a class, are called fields
    • Fields occupy memory
    • Fields usually are defined as private
    • Properties are accessor methods for class state
    • Properties are usually wrappers around fields
    • Properties can be read-only (only getter) or write-only (only setter)

    Static and Instance Class Members

    • Instance (normal) members are accessible through instances of the class
    • Static members are accessible without object creation, through class itself
    • Static fields:
      • Only one, per class definition
    • Instance fields:
      • One, per created object
    • Instance methods:
      • Have access to instance and static fields
    • Static methods
      • Only have access to static fields

    Reference Type/Value Type

    • Variables of reference types contains a reference to actual memory location
    • Variables of value types contains the actual data
    • Value types:
      • Assignment makes a copy of the data
    • Reference types:
      • Assignment make a copy of the reference
      • Multiple variable can reference the same data

    Enums

    • Enums are some related constants, grouped as a type
    • By default, enums are stored as int values
    • By default, the items values start from zero
    • Item values can be set explicitly
    • If the value of an item is not set, it is one more than the value of the previous item

    Inheritance

    • A class can inherit from another class
    • An inherited class is called sub-class or derived class
    • A class that another class is inherited from is called base-class
    • A derived class has all the members of the base class
    • An object of a derived class, also is of type of the base class

    Down Cast/Up Cast

    • Up Cast: casting from object of sub-type to object of base-type.
      • It is always valid and does not need an explicit cast
    • Down Cast: casting from object of base-type t object of sub-type.
      • It requires an explicit cast
      • It may not be possible, and can cause an exception
    • Every object can be cast to object type
    • is keyword is used to check that if on object is of some specified type. It shows that if the cast is possible or not
    • as keyword check the possibility of a cast, and if possible, performs the cast, otherwise returns null