C# Basics and Events Technion - Israel Institute of Technology - Last Update : Natan Bagrov & Oren Afek, June 2017 - Webcourse
←
→
Page content transcription
If your browser does not render page correctly, please read the page content below
C# Basics and Events Technion - Israel Institute of Technology Last Update : Natan Bagrov & Oren Afek, June 2017 1
C# • If programming languages were weapons …. C# is a powerful laser rifle strapped to a donkey, when taken off the donkey the laser doesn’t seem to work as well. https://9gag.com/gag/anXEbe0/if-programming-languages-were-weapons 2
Basic Program hello.cs using System; public class MyClass { public static void Main(string[] args) { Console.WriteLine("Hello, World!"); } } C:\> csc hello.cs … … C:\> hello.exe 3 236703 - Object-oriented Programming
Genealogy • Designer: Anders Hejlsberg (Microsoft) – Designer of Turbo Pascal, Visual J++, Delphi (Borland) • C Dynasty: Play on Words – C++ - increment C by one, C# - the musical note half tone above C • Yet another curly bracket programming language – Grouping: {} – Terminstic camp: statements terminated by ";" – C operators: ++ % != += && & ^, >>, ?: … – C like control: • if () … else … • for (…; …; …) … break …, while (…) … continue …, do … while (…) • switch (…) … case … default (no fall through, works on strings) 4 236703 - Object-oriented Programming
Design Principals All the Good Things: Simplicity, General Purpose, Portability, Object Oriented • Programmer Protection: – Strong Nominative Typing – Array Bounds Checking – Throws exception when out of bounds – Garbage Collection – Unless using unmanaged resources (same as Java) – Check against using uninitialized variables • Evolutionary: dramatic changes in each language version – Learned from Java mistakes (no checked exceptions, since Anders Hejlsberg doesn't know yet how to do these right) • Differences From Java? – Developed by Microsoft – Runs on CLR "Common Language Runtime“ (JVM @ Java) – Compiles to the CIL "Common Intermediate Language“ (Bytecode @ Java) – Support for "unsafe" features, including pointers. (N/A in Java) 5 – Anonymous types. (N/A in Java)
Object Oriented Purity • Global Variables? No – All variables are defined in functions/classes • Global Routines? No – All routines (functions) are defined in classes • Non OO Types? No – Even primitive types belong in the OO hierarchy 1.Equals(2) is legal • OO Control Flow? No – If, while, for, … are imperative statements • Pre-processor? Yes – Only conditional compilation and compiler directives 6 236703 - Object-oriented Programming
Value/Reference Semantics • Value Types – Simple types: char, int, float, … – Enum types public enum Color {Red, Blue, Green} – Struct types public struct Point { public int x, y; } – Nullable Value Types (next slide) – Wrapper Types: Int32 (int), Double (double), String (string), etc… • Reference Types – Classes, Interfaces, Delegates 7 236703 - Object-oriented Programming
Nullable Value Types • Nullable types are built-in value types wrapped with an ability to contain null. Back in the early, cold and unpleasant times of MATAM: int getNumberOfOrdersOnlyFirstCustomer(Customer* customers){ if(customers == NULL){ // throw? Maybe return -1? } if(customers[0] == NULL){ // throw? Maybe return -1? } if(customers[0]->orders == NULL){ // throw? Maybe return -1? } return customers[0]->orders->getSize()); } 8 236703 - Object-oriented Programming
Nullable Value Types • Nullable types are built-in value types wrapped with an ability to contain null. • C#’s way of defining the Optional Monad (of Java 8). int? GetNumberOfOrdersOnlyFirstCustomer( ICollection customers){ return customers?[0]?.Orders?.Count(); } ?. Is syntactic suger: if the receiver is null then return null. Else, make the operation on it. • Variable of T? can hold either a T value or null. • T must be value-type. No point using reference types, since they can be assigned with null anyway. • Use t.HasValue property to indicate if there is a value • Use t.Value property to get the unwrap and get the value 9 236703 - Object-oriented Programming
Inheritance Hierarchy • Classes: – Single Inheritance with common root: System.Object – Unified type system: includes all built-in types • System.ValueType: base class of all value types • Including void which is an alias for Object
Inheritance and Binding • Method Binding: static, unless method is declared virtual – virtual modifier cannot go with any of static, abstract, private or override modifiers. – Properties can be virtual • Overriding: inheritance is strict by default. – Overriding methods must be declared as such with override keyword – Cannot override non-virtual functions – will not compile – Use new modifier to indicate hiding – compiler will warn • Sealing: use sealed keyword to indicate that an overriding function cannot be overridden further – No point in sealing a "plain" virtual function. 11 11
Naming Conventions • Local variables & Fields : camelCase – string personName; • Classes, Enums, Structs, Methods and Properties : each word starts with a capital Letter (PascalCase) – class Person { ... } – void PrintPersonName(Person p) • Interfaces : starts with an I prefix – interface IEnumerable { ... } 12
Properties • Property: a field implemented with methods • Varieties: read only, write only, read-write • Contextual keywords: get, set, value (also add and del for events) – Provide specific meaning in the code (not otherwise reserved) public class Person { private string name; public string Name { get { return this.name; } set Person p = new Person(); { p.Name = “Eran Gilad”; //set if (value != “”) Console.WriteLine(p.Name); //get { this.name = value; } } } } 16 16
Auto Properties • Starting from C# 3.0, it is possible to declare an Auto Property. • The field can be omitted. public class Person { public int ID { get; } //read-only auto-property public string Name { get; set; } public int IQ { set; } //write-only auto-property } 17 236703 - Object-oriented Programming 17
Static Properties public struct HarryPotterBook { static private int count; // static constructor static HarryPotterBook() { count = she_wrote_it() ? 7 : 6; } // read-only static property static public int Count { get { return count; } } … } 18 236703 - Object-oriented Programming 18
Using Delegates Classic Example: when the room gets warmer The AC should turn on, and when it gets cooler, it should turn off. • Delegation: Software design and real-life: • Increasing Encapsulation by separating event and feedback • Which object “was there first?” • Scalability issues 19 19
Delegates • A type that references a method (similar to C++ function pointer) • Supply type safety: only a method that matches* the delegate's signature (return type and parameters) can be assigned to the delegate • Allow methods to be used as first class objects (e.g. passed as parameters) • Multicast (multiple methods can be assigned to a single delegate) • Delegates reference to a method, and thus associated with an instance (with the exception of static methods). • Support anonymous methods (later in this lesson) 20 236703 - Object-oriented 20
Delegate Type Hierarchy using System; using System.Reflection; delegate object MyDelegateType(Type o); public static class DelegateTypeHierarchy { private static string DelFunc(Type t) { as before... } private static void Ancestory(object o){ as before… } public static void Main() { Ancestory(new MyDelegateType(DelFunc)); } } MyDelegateType inherits from System.MulticastDelegate System.MulticastDelegate inherits from System.Delegate System.Delegate inherits from System.Object System.Object inherits from null 21 236703 - Object-oriented 21
Using Delegates • There are three steps in defining and using delegates: declaration assignment invocation 22 22
Using Delegates Step 1: Declaring a delegate – The observable: [modifiers] delegate return_type identifier([parameter_types]) //Declare a delegate type //Can be put inside the class to reduce namespace pollution public delegate void TemperatureChangeHandler(int c); public partial class TemperatureSensor { //Declare a delegate variable public TemperatureChangeHandler OnTempChanged; } 23 236703 - Object-oriented 23
Using Delegates The observer(s): public class SmartAirConditioner { public void ConnectToSensor(TemperatureSensor ts) { //Assign a delegate – start observing ts ts.OnTempChanged += TemperatureChangedCallback; } public void TemperatureChangedCallback(int t) { if(t > 24 && IsOff) StartCooling(); else if(t < 18 && IsOff) StartWarming(); else TurnOff(); } public void StartCooling(){… IsOff = false; …} public void StartWarming(){… IsOff = false; …} public void TurnOff(){ IsOff = true; … } } 24 236703 - Object-oriented 24
Using Delegates Step 2: Assigning a delegate to a variable – Assign a delegate using = operator – Add a delegate using += operator • has a default implementation, but the programmer can provide his own add. – Remove a delegate using -= operator • has a default implementation, but the programmer can provide his own remove. public static void Main(string[] args) { var ts = new TemperatureSensor(); ... var ac = new SmartAirConditioner(); ac.ConnectToSensor(ts); } public void ConnectToSensor(TemperatureSensor ts) { 25 ts.OnTempChanged += TemperatureChangedCallback; 236703 - Object-oriented } 25
Using Delegates Step 3: Invoking the delegate – The observable: public partial class TemperatureSensor { //This method invoked by some hardware…(for this example) void TemperatureChanged(int t) { if (null != OnTempChanged) OnTempChanged(t); //Invoke all delegates } } 26 236703 - Object-oriented 26
Problems? • Consider the following code samples: public void ConnectToSensor(TemperatureSensor ts) { ts.OnTempChanged = TemperatureChangedCallback; //null is even worse! } Problem 1 public void ConnectToSensor(TemperatureSensor ts) { ts.OnTempChanged(42); Problem 2 } public static void Main() { var ts = new TemperatureSensor(); ... var ac = new SmartAirConditioner(); ac.ConnectToSensor(ts); 27 } 236703 - Object-oriented 27
The event keyword • The event keyword can be associated with a field of type delegate • An event can only appear on the lhs of += or -= except when used from the defining class – Excluding derived classes as well – The defining class treats it like any other delegate (assign it with =, invoke it, etc.) – Event are like properties, which have two actions: add, remove. • Events may appear in interfaces! Our Example: royal social conduct If King is happy: notify all men in the kingdom If King is ill: notify noblemen only. 28 236703 - Object-oriented 28
King, Nobleman and Citizens Kingdom Man namespace Life static abstract Notify delegate Citizen Nobleman King State sealed concrete concrete enum • Name: every man has a name • Title: every man has a title, based on his status and name – Realized by method ToString() • Service: every man can be set to service any number of kings. – Method service(King k) in class Man 29 236703 - Object-oriented 29
Delegate Notify • Type definition: A reference to a method (to be called when a king changes his state) namespace Kingdom { delegate object Notify(King k); Notify … delegate } • Simple (uninteresting) use: void foo(King k){ Notify bar; // A delegate variable of type Notify bar = FunctionDescriptor; … object o = bar(k); // Invoke FunctionDescriptor } • A more interesting use: class Foo { event Notify baz; // An event of type Notify public void foo(King k) { baz += FunctionDescriptor; … baz(k); // Invoke FunctionDescriptor } } 30 236703 - Object-oriented 30
Delegates and Events • Delegate type definition: namespace Kingdom { delegate object Notify(King k); … } • Event definition: namespace Kingdom { class King : Man { public event Notify OnKingIllness, OnKingHappiness; … } Why were OnKingIllness, OnKingHappiness declared as events? 31 236703 - Object-oriented 31
Class King and Enum State namespace Kingdom { … enum State { Happy, Ill }; … class King : Man { public State state; public King(String name): base(name){state = State.Ill;} State sealed override public string ToString() { enum return "His Majesty, King " + Name; } // events for those interested in the King's being. public event Notify OnKingIllness, OnKingHappiness; //returns last listener’s return value – use GetInvocationList() to iterate the registered callbacks public object BeIll() { state = State.Ill; return OnKingIllness!= null ? OnKingIllness(this): null; } King //returns last listener’s return value - use GetInvocationList() to iterate the registered callbacks public object BeHappy() { concrete state = State.Happy; return OnKingHappiness!= null ? OnKingHappiness(this): null; } } 32 236703 - Object-oriented 32
Class Man namespace Kingdom { abstract class Man { protected readonly String Name; public Man(String name) { Name = name; } abstract override public String ToString(); // Every man is happy when a King he serves is happy. virtual public void Serve(King k) { k.OnKingHappiness += Happy; } Man public Man Happy(Man m) { abstract Console.WriteLine(this + “ is happy to hear that " + m + " is happy.“) return this; } } … } 33 236703 - Object-oriented 33
Registration of an Actual Delegate • Actual Delegate: a method for notification namespace Kingdom { abstract class Man { … public Man Happy(Man m) { Console.WriteLine(this + “ is happy to hear that " + m + " is happy.“) return this; } … } • Register a delegate: with += operator namespace Kingdom { abstract class Man { … virtual public void Serve(King k) { k.OnKingHappiness += Happy; } …} 34 236703 - Object-oriented 34
Classes Citizen and Nobleman namespace Kingdom {… sealed class Citizen : Man { public Citizen(string name) : base(name) { } override public string ToString() { return "Citizen " + Name; } Citizen } sealed class Nobleman : Man { public Nobleman(string name) : base(name) { } override public string ToString() { return "Nobleman " + Name; } public Nobleman Ill(Man m) { Console.WriteLine(this + " is sorry to hear that " + m + " is ill."); return this; } override public void Serve(King k) { Nobleman base.Serve(k); concrete k.OnKingIllness += Ill; } } …{ 35 236703 - Object-oriented 35
Main Application static class Life { static void Main() { King R = new King("Richard"); Life King G = new King("George"); Citizen a = new Citizen("Al"); static Citizen b = new Citizen("Bob"); Nobleman v = new Nobleman("Virgil"); a.Serve(R); Richard b.Serve(R); b.Serve(G); George v.Serve(R); G.Serve(R); R.beIll(); R.beHappy(); Console.WriteLine("----"); Al G.beIll(); G.beHappy(); Virgil Console.WriteLine("----"); Bob } } 36 236703 - Object-oriented 36
Output Scenario 1. King Richard becomes ill Richard 2. King Richard becomes happy George 3. King George becomes ill 4. King George becomes happy Remember, every man is happy when a king Al he serves is happy, but only a Noblemen is to Virgil be notified when his king is ill. Bob Noblemen Virgil is sorry to hear that His Majesty, King Richard is ill. Citizen Al is happy to hear that His Majesty, King Richard is happy. Citizen Bob is happy to hear that His Majesty, King Richard is happy. Noblemen Virgil is happy to hear that His Majesty, King Richard is happy. His Majesty, King George is happy to hear that His Majesty, King Richard is happy. ---- Citizen Bob is happy to hear that His Majesty, King George is happy. ---- 37 236703 - Object-oriented 37
Indexers • Purpose: Implement array access with methods • Similar to properties (though no static indexers) – Syntax: modifiers returnType this[IndexType pos] – Variations: • multi-parameters indexers • read-only, write-only and read-write indexers • overloaded indexers class List { … private Node Nth(Node n, uint d) { if (n == null) throw new Exception("out of range"); return d == 0 ? n : Nth(n.Next, d-1); } public object this[uint i] { // indexer using ordinal position get { return Nth(first, i).Data; } set { Nth(first, i).Data = value; } } } 39 236703 - Object-oriented Programming 39
Using the Indexer class List { static void Main() { const uint n = 5; List sq = new List(n); for (uint i = 0; i < n; i++) sq[i] = i * i; for (uint i = 0; i < n; i++) Console.WriteLine(i + "^2 = " + sq[i]); } } 0^2 = 0 1^2 = 1 2^2 = 4 3^2 = 9 4^2 = 16 40 236703 - Object-oriented Programming 40
Extension methods • Extension methods are a special kind of static method • Extension methods allow "adding" methods to existing types without modifying the original type public static class DateTimeExtention { public static DateTime ToIsraeliTime(this DateTime p_dt){ return p_dt.ToUniversalTime().AddHours(3); } } DateTime utc = DateTime.UtcNow; Assert.AreEqual(utc.AddHours(3),utc.ToIsraeliTime()); DateTime now = DateTime.Now; Assert.AreEqual(now, now.ToIsraeliTime()); // Yay! The test passes. So why do we need ToIsraeliTime() extension anyway? Why not use DateTime.Now? 42 236703 - Object-oriented Programming
Rules for the extension methods • The first parameter specifies which type the method operates on – the parameter is preceded by this modifier • Extension methods can be used only when the namespace in which the methods are defined is explicitly imported with a using directive. • Extension methods cannot access private variables in the type they are extending • Extension methods can extend a class or interface • An extension method with the same name and signature as an interface or class method will never be called. – At compile time, extension methods always have lower priority than instance methods defined in the type itself 43 236703 - Object-oriented Programming 43
Anonymous Methods • Anonymous methods represent a way to pass a code block as a delegate parameter. delegate void Printer(string s); class AnonymousMethods{ static void Main() { Printer p += delegate(string j) { Console.WriteLine(j);}; p("The delegate using the anonymous method is called."); p = new Printer(AnonymousMethods.DoWork); p("The delegate using the named method is called."); } static void DoWork(string k) { Console.WriteLine(k); } } The delegate using the anonymous method is called. The delegate using the named method is called. 44 44
Anonymous Methods (2) delegate void Printer2(); class AnonymousMethods { static void Main(string[] args) { string j = "The delegate with local variable is called."; Printer2 p2 = delegate() {Console.WriteLine(j);}; p2(); } The delegate with local variable is called. Note: C# 7.0 introduces Inner-Methods… 45 45
Lambda Expressions • A lambda expressions is an anonymous function, that use the lambda operator =>. – The left side of the lambda operator specifies the input parameters (if any) – The right side holds the expression or statement block delegate void Printer(string s); class LambdaExpressions{ static void Main(string[] args) { Printer p = j => Console.WriteLine(j); p("The delegate using the anonymous method is called."); } } The delegate using the anonymous method is called. 46 46
Anonymous and dynamic Types class MyClass { public static dynamic Foo(){ return new {Field1 = "Value1“, Field2 = 69}; } } static dynamic what??? Foo() is a static-method of MyClass, that returns dynamic (since C# 4.0) type (methods don’t have to be static to return dynamic type) • dynamic object is an object whose operations will be resolved at run-time. • Anonymous Types cannot have methods or fields. Properties Only! • Why not use Object or Generics then? It has same features, no? • Object & are resolved at compile-time! • void Print(Object d) {Console.WriteLine(d.Field1);} won’t compile • void Print(T d) {Console.WriteLine(d.Field1);} won’t compile • void Print(dynamic d) {Console.WriteLine(d.Field1);} will throw a RuntimeException when called if d has no Field1 property. 47 47
Anonymous Types Benefits of Anonymous Types • The best way to obtain “non-types” capabilities • as in JavaScript, Python • Saves time and doesn’t pollute the namespace • For example: public static string ToJson(object o) Can use (dynamic o) as well { return string.Format("{{" + Environment.NewLine + "{0}" + Environment.NewLine + "}}", string.Join(Environment.NewLine, o.GetType() .GetProperties().ToList() .ConvertAll(p => $"\"{p.Name}\" : \" {p.GetValue(o)} \""))); } 48 48
Anonymous Types Benefits of Anonymous Types • The best way to obtain “non-types” capabilities • as in JavaScript, Python • Saves time and doesn’t pollute the namespace • For example: class Person Console.WriteLine( { ToJson( public string FirstName {get; set;} new { public string LastName {get; set;} FirstName = “Roy”, public int Grade {get; set;} LastName = “Moshe”, } Grade = 95 Person p = new Person(); } ); p.FirstName = “Roy”; p.LastName = “Moshe”; p.Grade = 95; Console.WriteLine(ToJson(p)); 49 49
Summary – C# Unique Features • Properties: implement fields with functions – Conforms to Eiffel Principle of Uniform Reference. • Delegates: type safe function pointers – Events: list of delegates. • Static classes • Seamless integration of value semantics – Including nullable values. C# 7.0 is out: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in- csharp-7-0/ 50 236703 - Object-oriented 50
Let’s play some poker 51
You can also read