FUN WITH C# EPISODE XIII INTERFACES STRIKE BACK
CLI Type System All types Reference types (allocated on managed heap) PointersValue types (allocated in-place [with exceptions] ) Classes (e.g. strings) Interfaces ArraysDelegates Simple types (Int32, Int64, Double, Boolean, Char, …) Nullables Enumerations Structures User defined structures
CLI Type Inheritance System.Object (C# keyword: object ) user-defined classes (C# keyword: class ) delegates (C# keyword: delegate ) pointers (C#: Type * ) System.Delegate System.MulticastDelegate System.ValueType System.Enum System.Array arrays (C#: Type[] or Type[,] ) System.String (C# keyword: string ) interfaces (C# keyword: interface ) user-defined structures (C# keyword: struct ) enumerations (C# keyword: enum ) System.Int32 (C# keyword: int ) System.Int64 (C# keyword: long ) System.Double (C# keyword: double ) System.Boolean (C# keyword: bool ) … simple types System.Nullable (C#: Type? )
Interfaces
Interface Constraints: Is It Correct? interface I1 { void m(); } interface I2 { void m(); } class B : I1, I2 { public void m() { Console.WriteLine("B.m()"); } class Y where T : I1, I2 { public static void m(T t) { t.m(); } class Program { static void Main(string[] args) { new B().m(); Y.m(new B()); }
Implementing Generic Interfaces interface I { void m(T x); T m(); } class A : I, I { ? }
Implementing Generic Interfaces interface I { void m(T x); T m(); } class A : I, I { public void m(int x) { Console.WriteLine("int m"); } public void m(long x) { Console.WriteLine("long m"); } public int m() { return -1; } long I.m() { return -2; } } class Program { static void Main(string[] args) { A a = new A(); a.m(0); a.m(0L);// Same as a.m(0l); ((I ) a).m(0); Console.WriteLine(a.m()); Console.WriteLine(((I ) a).m()); }
Implementing Generic Interfaces interface I { void m(T x); T m(); } class A : I, I { public void m(int x) { Console.WriteLine("int m"); } public void m(long x) { Console.WriteLine("long m"); } public int m() { return -1; } long I.m() { return -2; } } class Program { static void Main(string[] args) { A a = new A(); a.m(0); a.m(0L);// Same as a.m(0l); ((I ) a).m(0); Console.WriteLine(a.m()); Console.WriteLine(((I ) a).m()); }
Interfaces and Value Types
IDisposable public interface IDisposable { void Dispose() } public class ObjectDisposedException : InvalidOperationException {}
Class System.Object Topmost base class of all other classes class Object { protected object MemberwiseClone() {...} public Type GetType() {...} public virtual bool Equals (object o) {...} public virtual string ToString() {...} public virtual int GetHashCode() {...} public static bool ReferenceEquals(object objA, object objB); }
IEqualityComparer IEqualityComparer EqualityComparer.Default: a default implementation of a IEqualityComparer for type T public interface IEqualityComparer { int GetHashCode(T obj); bool Equals(T x, T y); } Used by Dictionary and HashSet collections.
Class System.Object Topmost base class of all other classes class Object { protected object MemberwiseClone() {...} public Type GetType() {...} public virtual bool Equals (object o) {...} public virtual string ToString() {...} public virtual int GetHashCode() {...} public static bool ReferenceEquals(object objA, object objB); }
Sorting: IComparable and IComparer IComparable is interface for types with order classes implementing IComparable are values types like Int32, Double, DateTime, … class Enum as base class of all enumeration types class String IComparer is interface for the realization of compare operators public interface IComparer { int Compare(object x, object y); // 0 if x > y } public interface IComparer { int Compare(T x, T y); // 0 if x > y } public interface IComparable { int CompareTo(object obj); // 0 if this > obj } public interface IComparable { int CompareTo(T obj); // 0 if this > obj }
Custom IComparer Implementation Creation of table of strings: string[][] Table = { new string[] {"John", "Dow", "programmer"}, new string[] {"Bob", "Smith", "agent"}, new string[] {"Jane", "Dow", "assistant"}, new string[] {"Jack", "Sparrow", "manager"} }; Printing the table: foreach (string[] Row in Table) { Console.WriteLine(String.Join(", ", Row)); }
Custom IComparer Implementation (2) Comparer for single table (array) column: class ArrayComparer : IComparer where T : IComparable { private int m_Index; public ArrayComparer(int Index) { m_Index = Index; } public int Compare(T[] x, T[] y) { return x[m_Index].CompareTo(y[m_Index]); } Printing the table: Array.Sort(Employees, new ArrayComparer (2)); foreach (string[] Row in Employees) { Console.WriteLine(String.Join(", ", Row)); } Bob, Smith, agent Jane, Dow, assistant Jack, Sparrow, manager John, Dow, programmer
"BCL v2-friendly" Custom Classes 1/3 In order to cooperate smoothly with other BCL classes in the framework 2.0, custom classes should: override ToString and GetHashCode overload == and != (implement ICloneable) public interface ICloneable { object Clone(); } class MyClass : ICloneable { public object Clone() { return MemberwiseClone(); } }
"BCL v2-friendly" Custom Classes 2/3 implement IComparable and IComparable public interface IComparable { int CompareTo(object obj); // 0: this > obj } public interface IComparable { int CompareTo(T obj); // 0: this > obj } class Fraction : IComparable, IComparable { int n, d; public int CompareTo(object obj) { if (f == null) return 1; if (!(obj is Fraction)) throw new ArgumentException(“Must be of Fraction type.”, “obj”); return CompareTo((Fraction) obj); } public int CompareTo(Fraction f) { if (f == null) return 1; return n*f.d – f.n*d }
"BCL v2-friendly" Custom Classes 3/3 override Equals(object) and implement IEquatable public class Object { public virtual bool Equals(Object obj); … } public interface IEquatable { bool Equals(T other); } class Fraction : IEquatable { // equal to class Fraction : object, IEquatable int n, d; public override bool Equals(object obj) { Fraction f = obj as Fraction; if (f == null) return false; return Equals(f); } public bool Equals(Fraction f) { return f.n == n && f.d == d; }
Mé předměty o.NET a C# NPRG035 ZS 2/2 Zk/Z “Jazyk C# a platforma.NET” Základy jazyka, knihoven a běhového prostředí (pro kvalitní OOP), SW inženýrství NPRG038 LS 2/2 Zk/Z “Programování pro.NET I“ Pokročilé možnosti jazyka a knihoven potřebné pro „moderní“ programování: delegáti, vlákna a asynchronní programování, síťování, Reflection, generování kódu, enumerační metody, LINQ to Objects NPRG057 LS 2/0 Zk “Programování pro.NET II” „interface s okolím“: bezpečnost (.NET Security), interoperabilita s C++, unsafe kód, Python, hostování CLR v C++, vzdálené volání objektů: Remoting, WCF, databáze, ?WF? Od AR 2015/2016 zakončeno pouze přehledovou zkouškou bez „zápočtového“ programu ?NPRG061? LS 0/2 Z (1 kredit) “Programování uživatelských rozhraní v.NET” „interface s uživatelem“: WinForms, WPF, ASP.NET WebForms, ASP.NET MVC, lokalizace a globalizace aplikací, programování her a visualizačních aplikací ve 2D a 3D (např. WaveEngine, apod.) Pilotní běh “po večerech“ v LS 2015/2016 Vypsané od AR 2016/2017 – zápočet za 1 kredit za uznaný zápočtový program z NPRG035 nebo NPRG038 s netriviálním uživatelským rozhraním (všechny 3 letní předměty je principiálně možné studovat paralelně jako navazující jen na zimní NPRG035)