The C♯ Language

C♯ documentation

The Required Tutorial

Codecademy

Language Basics

  • C, C++,Java inspired/based -- general purpose
  • Traditional compiled language, but to an intermediate language (like Java) with garbage collection
  • Object-oriented, imperative/procedural, with functional programming features
  • Statically typed, strongly typed
  • Originally developed by Microsoft with .NET, now internationally standardized
  • Native on Windows, Mono on Linux, now cross-platform via .NET Core
  • Big, expressive language

Whenever you learn a new construct in a programming language, you should ask these three questions:

1.What is the syntax?

2.What are the type-checking rules?

3.What are the evaluation rules?

EXAMPLE

■Variables:

–Syntax: a sequence of letters, underscores, etc.

–Type-checking: look up the variable in the current static environment and use that type

–Evaluation: look up the variable in the current dynamic environment and use that value

Data and Types

Numeric Types

int a = 123;
System.Int32 b = 123;

 

sbyte short, int, long, float, double, or decimal
byte short, ushort, int, uint, long, ulong, float, double, or decimal
short int, long, float, double, or decimal
ushort int, uint, long, ulong, float, double, or decimal
int long, float, double, or decimal
uint long, ulong, float, double, or decimal
long float, double, or decimal
ulong float, double, or decimal
float double

Other Value Types

  • char (System.Char)
  • bool (System.Boolean)
  • struct
  • enum

enum Season {
    Spring,
    Summer,
    Autumn,
    Winter }

Reference Types

  • object (System.Object)
  • string (System.String)
  • interface
  • array (System.Array)
  • delegate
int    a = 5;
double b = 30.43;
bool   c = false;
char   d = 'Z';
string e = "Welcome to C#";
ArrayList f = new ArrayList();

Array and Struct

char[] vowels  = new char[5];
char[] vowels2 = new char[] {'a','e','i','o','u'};
char[] vowels3 = {'a','e','i','o','u'};
                    
for(int i = 0; i < vowels.Length; i++)
{
    Console.Write(vowels[i]);
}
                    
public struct Point
{
    public int X, Y;
    public Point(int x, int y) { X = x; Y = y; }
}

Point p = new Point(4,5);

Basic Program Structure

using System;

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

namespace MyConsoleAppName
{
    enum BallType
    {
        Basketball,
        Baseball,
        Soccerball,
        Volleyball
    }

    class Ball
    {
        private double radius;
        private BallType type;

        public Ball(double radius, BallType type)
        {
            this.radius = radius;
            this.type = type;
        }
        public BallType GetBallType () {return type;}
    }
}                            

Control Structures

All the usual

  • if-else
  • while, do-while
  • for, foreach
  • continue, break
  • switch-case
  • try-catch-finally
int x = 10;

// Argument must be a boolean
if(x < 20)
{
    Console.WriteLine("Less than");
}
else
{
    Console.WriteLine("Greater than or equal to");
}

Expressions and Operators

No surprises here. All the usual expression operators.

 

See later slides for unusual operators.

Methods

  • Base syntax is exactly as C, C++ and Java
  • No "naked" functions allowed; all functions go inside classes and are called methods
  • static methods can be called like functions without an instance of the class.
  • Program entry point is a static method
  • Can pass methods to methods as parameters (see Function delegates later)

Parameter Passing


 

using System;

// "Normal" scenario
class Test
{
    static void Foo(int p)
    {
        Console.WriteLine(p);
    }
    
    static void Main()
    {
        Foo(8);
    }
}
using System;

class Test
{
    static void Foo(int p)
    {
        p = p + 1;  
        Console.WriteLine(p);
    }
    
    static void Main()
    {
        int x = 8;
        Foo(x);
        Console.Writeline(x);
    }
}
using System;

class Test         // ref modifier
{
    static void Foo(ref int p)
    {
        Console.WriteLine(p);
        p = p + 1;
    }
    
    static void Main()
    {
        int x = 8;
        Foo(ref x);
        Console.WriteLine(x); // x is now 9
    }
}
using System;

class Test         // ref modifier useful swap
{
    static void Swap(ref string a, ref string b)
    {
       string temp = a;
       a = b;
       b = temp;   
    }

    static void Main()
    {
        string x = "Penn";
        string y = "Teller";  
        Swap (ref x, ref y);
        Console.WriteLine (x);
        Console.WriteLine (y);
    }
}
// outputs:
//     Teller
//     Penn
using System;

class Test         // out modifier
{
    static void Split (string name, out string firstNames, out string                                lastName)
    {
       int i = name.LastIndexOf (' ');
       firstNames = name.Substring (0, i);
       lastName   = name.Substring (i + 1);
    }

    static void Main()
    {
        string a, b;
        Split ("Stevie Ray Vaughan", out a, out b);
        Console.WriteLine (a);
        Console.WriteLine (b);
    }
}
// outputs:
//     Stevie Ray
//     Vaughan
using System;

class Test     // params modifier
{
    static int Sum (params int[] ints)
    {
        int sum = 0;
        for (int i = 0; i < ints.Length; i++)
            sum += ints[i];
        return sum;
    }
    static void Main()
    {
        int total = Sum (1, 2, 3, 4);
        Console.WriteLine (total);
    }
}
using System;

class Test         // Optional parameters
{
    static string JoinWith(char a, char b, string del = ",")
    {
        // C# 6 "interpolated string literal
        return $"{a}{del}{b}";
    }
    
    static void Main()
    {
        Console.WriteLine( JoinWith('u','v') );
        Console.WriteLine( JoinWith('u','v',"___") );
    }
}
// outputs:
//  u,v
//  u___v
class NamedExample
{
    static void Main(string[] args)
    {
        // The method can be called in the normal way, by using positional arguments.
        PrintOrderDetails("Gift Shop", 31, "Red Mug");

        // Named arguments can be supplied for the parameters in any order.
        PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
        PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);

        // Named arguments mixed with positional arguments are valid
        // as long as they are used in their correct position.
        PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
        PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); // C# 7.2 onwards
        PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug");               // C# 7.2 onwards

        // However, mixed arguments are invalid if used out-of-order.
        // The following statements will cause a compiler error.
        // PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");
        // PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug");
        // PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop");
    }

    static void PrintOrderDetails(string sellerName, int orderNum, string productName)
    {
        if (string.IsNullOrWhiteSpace(sellerName))
        {
            throw new ArgumentException(message: "Seller name cannot be null or empty.", paramName: nameof(sellerName));
        }

        Console.WriteLine($"Seller: {sellerName}, Order #: {orderNum}, Product: {productName}");
    }
}
// Expression-bodied function members 
// general syntax: member => expression;
public int AddTwo(int a, int b) => a + b;

Var and Nulls

// Implicitly typed local variables

var i = 5;
                    
var adj = "a superlative";
                    
var arr = new[] {1,2,3};

var expr =
    from c in customers
    where c.City == "London"
    select c;

Null-Coalescing Operator (??)

 

string s = null;
string s1 = s ?? "something else"; 
//s1 evaluates to "something else"

string s = "Hello World";
string s1 = s ?? "Not a string";
//s1 evaluates to "Hello World"

 

Null-Conditional Operator (?.)

 

// Prevents NullReferenceException
// AKA: Safe navigation operator
System.Text.StringBuilder sb = null;
string s = sb?.ToString();

// short circuits and is safe
x?.y?.z;

System.Text.StringBuilder sb = null;
string s = sb?.ToString() ?? "something else";

Nullable Types (?)

string s = null;    // just fine
int a = null;       // does not compile

int? id = null;     // OK
System.Nullable<int> id = null;
                    
// common MVC pattern
public ActionResult Details(int? id)
{
    if(id == null)        // or !id.HasValue
    {
        return new HttpStatusCodeResult(400, "Missing user identifier in request");
    }
    User user = db.Users.Find(id);
    // ...
}//Example Lab 4

Operator Lifting with Nullable Types

int? x = 8;
int? y = 100;
int? z = null;      // i.e. System.Nullable<int> z

// operators are lifted from int
// Normal:
x == y
x + y
x < y

// But must worry about effect of null
x == z     // False
x + z      // null
x < z      // False
x > z      // False

Namespaces 



namespace namespace_name {
   // code declarations
}


namespace_name.item_name;
using System;

namespace first_space {
   class namespace_cl {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}
namespace second_space {
   class namespace_cl {
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}
class TestClass {
   static void Main(string[] args) {
      first_space.namespace_cl fc = new first_space.namespace_cl();
      second_space.namespace_cl sc = new second_space.namespace_cl();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

Namespaces - The Using Keyword

using System;
using first_space;
using second_space;

namespace first_space {
   class abc {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}
namespace second_space {
   class efg {
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}   
class TestClass {
   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

Nested Namespaces

namespace namespace_name1 {
   
   // code declarations
   namespace namespace_name2 {
      // code declarations
   }
}
using System;
using first_space;
using first_space.second_space;

namespace first_space {
   class abc {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
   namespace second_space {
      class efg {
         public void func() {
            Console.WriteLine("Inside second_space");
         }
      }
   }   
}
class TestClass {
   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}
public partial class Employee
{
    public void DoWork()
    {
    }
}

public partial class Employee
{
    public void GoToLunch()
    {
    }
}

Partial Classes

// Auto generated code in: file1.cs
namespace MyApp
{
    partial class MyClass { public void MyMethod(){} }
    // other members
}
                    
// Your code in: file2.cs
namespace MyApp
{
    partial class MyClass { public void OtherMember(){} }
}

Classes

using System;

public class Wolf : Canine, IEquatable<Wolf>
{
    public string Name = "Wolfie";
    public string Owner;
    public int Legs;
    private static int totalCount;
    private DateTime birthday;
    
    public Wolf() {}
    public Wolf(string name)
    {
        this.Name = name;
    }
    //...
}

Object Initializers


Wolf w1 = new Wolf("Sharp Teeth") { Owner="Me", Legs=4 };
Wolf w2 = new Wolf { Name="Ghost", Owner="John Snow", Legs=4 };

Properties

public class Stock
{
    private decimal maxPrice;   // private "backing field"
    
    public decimal MaxPrice
    {
        get { return maxPrice; }
        set { maxPrice = value; }
    }
    
    // Automatic property
    public decimal CurrentPrice { get; set; }
}
var s = new Stock();
s.MaxPrice = 99.99M;
s.CurrentPrice = 89.99M;
Console.WriteLine(s.CurrentPrice);
// Read-only property
string symbol;            // set in the constructor

public string Symbol
{
    get { return symbol; }
}

// Expression-bodied property (also read-only)
public decimal Worth => currentPrice * sharesOwned;
(public decimal Worth {get{return currentPrice * 
sharesOwned;}})
                
// Initializer
public int Volume { get; set; } = 100;

Typical Class in MVC

public partial class Comment
{
    public Comment(){}

    public int ID { get; set; }

    public DateTime SubmissionDate { get; set; }

    public string Body { get; set; }
}

Object and Boxing/Unboxing

// System.Object or object is the base of the object hierarchy
object o = new House();
                    
// C# has boxing and unboxing
int age = 32;
object obj = age;
                    
int myAge = (int)obj;

Delegates

// Declare a new type
public delegate double BinaryOperator( double a, double b );

// Create methods we want to use
public static double Add( double a, double b ) => a + b;
public static double Sub( double a, double b ) => a - b;
public static double Div( double a, double b ) => a / b;
public static double Mul( double a, double b ) => a * b;

    // Create an instance of the delegate type
    BinaryOperator bop = Sub;

    // Use it
    Console.WriteLine( "7 - 9.3 = " + bop(7,9.3) );

 

  • Is type safe
  • Used to create callback functions
  • Used in lambda functions (expressions) and LINQ
  • Useful in MVC and with testing
  • Has other features
    • Multi-cast
    • Integrates with events
    • Can use generics

Lambda Functions

// Expression Lambdas
// (input parameters) => expression

x => x * x
(x,y) => x == y
(int x, string s) => s.Length > x
// Statement Lambdas
// (input parameters) => { statement1; statement2; statement3; }

() => {Console.WriteLine("Hello Lambda!");}
(x,y) => { return x == y; }      // weird way to write that!

Consider Generic Delegates

// C# 3.0 defined
namespace System{
    public delegate TResult Func<out TResult>();
    public delegate TResult Func<in T, out TResult>(T arg);
    public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
}
Func<double, double, double> sum = (x,y) => x + y;

public static IEnumerable<U> Map(Func<T, U> fn, IEnumerable<T> list)
{
    //apply fn to list and return resulting new list
}
var output = Map( x => x * x, nums );

Extension Methods

  • Extend an existing type with new methods
  • Doesn't alter original type
  • Need to add a using statement for extension class in order to use it (i.e. using System.Linq; for LINQ operators)
  • Needs to be a static method in a static class
  • this modifier as first parameter
  • Works for interface types too
// "Add" to string class
public static class StringHelper
{
    public static bool IsCapitalized (this string s)
    {
        if (string.IsNullOrEmpty(s)) 
            return false;
        return char.IsUpper (s[0]);
    }
}               
// Call it as a built-in method
"Perth".IsCapitalized();
// or as a static method
StringHelper.IsCapitalized("Perth");
                    
// How it's translated:
arg0.Method(arg1, arg2, ...);              // Extension method call
StaticClass.Method(arg0, arg1, arg2, ...); // Static method call
// Map example from previous slide
// written as an extension method
Func<double, double, double> sum = (x,y) => x + y;

public static IEnumerable<U> Map(this IEnumerable<T> list, Func<T, U> fn)
{
    //apply fn to list and return resulting new list
}

var output = nums.Map( x => x * x );

Chaining

Look at some definitions in IEnumerable<T>

int[] ints = { 10, 45, 15, 39, 21, 26 };
var result = ints.OrderBy(g => g).Take(4).Average();

// Versus
var result = Average(Take(OrderBy(ints, g=>g),4));

Anonymous Types

  • Simple un-named reference type; inherits directly from object
  • Compiler generates code using a template to create the class
  • Must use a var keyword to create new objects of this type
  • You automatically get an .Equals() that compares members for equality
  • Access by name (property), i.e. like Name/Value pairs
var obj = new {Name = "Jane", Age = 28, CellNumber = "555-555-1111" };

 // or
  
var obj2 = new { 
    Store = "ShoesForLess", 
    Categories = new String[]{"Running","Leisure","Dress","Sandals"},
    Date = DateTime.Now
    }

Console.WriteLine(obj2.Store);

Useful in LINQ select queries

var categories = db.ProductCategories
                   .OrderBy( pc => pc.Name )
                   .Select( pc => new { Name = pc.Name,
                                        Id   = pc.ProductCategoryID } );

Collections

Built-in data structures of both generic and non-generic types

  • List, ArrayList, LinkedList, ImmutableList, ...
  • Queue, Stack
  • HashSet, SortedSet, Dictionary, OrderedDictionary, ...
  • Generic versions: LinkedList<T>

Yup, the usual:

using System;
using System.Collections;
public class SamplesArrayList  
{
   public static void Main() 
   {
      // Creates and initializes a new ArrayList.
      ArrayList myAL = new ArrayList();
      myAL.Add("Hello");
      myAL.Add("World");
      myAL.Add("!");

      // Displays the properties and values of the ArrayList.
      Console.WriteLine( "myAL" );
      Console.WriteLine( "    Count:    {0}", myAL.Count );
      Console.WriteLine( "    Capacity: {0}", myAL.Capacity );
      Console.Write( "    Values:" );
      PrintValues( myAL );
   }

   public static void PrintValues( IEnumerable myList )  
   {
      foreach ( object obj in myList )
         Console.Write( "   {0}", obj );
      Console.WriteLine();
   }
}

And in generic form

// using System.Collections.Generic List<T>
List<string> dinosaurs = new List<string>();

Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);

dinosaurs.Add("Tyrannosaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Deinonychus");
dinosaurs.Add("Compsognathus");
Console.WriteLine();
foreach(string dinosaur in dinosaurs)
{
    Console.WriteLine(dinosaur);
}

We frequently use objects of these types:

and should look closely at these interfaces

Copy of C# Language

By drmorgan

Copy of C# Language

  • 3