C# versus Java Hanspeter Mössenböck Universität Linz Institut für Praktische Informatik (Systemsoftware) [email protected] Der Kontext Java-Technologie .NET-Technologie Entstehungsjahr 1995 2002 Betriebssysteme Unix/Linux, Windows, MacOS, ... Windows (Linux, MacOS X) Leitidee Eine Sprache auf vielen Plattformen Viele Sprachen auf einer Plattform (VB, C++, J#, Eiffel, Fortran, ...) VM Java-VM Common Language Runtime Zwischencode Java-Bytecodes Common Intermediate Language JIT-Compilation per Methode gesamt Komponenten Beans, EJB Assemblies Versionierung - ja Applets ja - Datenbanken JDBC ADO.NET Web-Programmierung Servlets, JSP ASP.NET 2 Merkmale von C# Sehr ähnlich zu Java 70% Java, 10% C++, 10% Visual Basic, 10% neu Wie in Java Wie in C++ • • • • • • • • • • • (Operator) Overloading • Zeigerarithmetik in Unsafe Code • Einige syntaktische Details Objektorientierung (einf. Vererbung) Interfaces Exceptions Threads Namespaces (wie Packages) Strenge Typprüfung Garbage Collection Reflection Dynamisches Laden von Code ... 3 Neue Features in C# Wirklich neu (vs. Java) "Syntactic Sugar" • • • • • • • • • • • Komponentenunterstützung - Properties - Events • Delegates • Indexers • Operator Overloading • foreach-Iterator • Boxing/Unboxing • ... Referenzparameter Objekte am Stack (Structs) Blockmatrizen Enumerationen Uniformes Typsystem goto Systemnahes Programmieren Versionierung Attribute Kompatibel mit anderen .NETSprachen 4 Typsystem von C# Typen Werttypen Einfache Typen bool char sbyte short int long byte ushort uint ulong Enums Referenztypen Structs float double decimal Klassen Interfaces Arrays Delegates Benutzerdefinierbare Typen Alle Typen sind kompatibel mit object - können object-Variablen zugewiesen werden - verstehen object-Operationen 5 Boxing und Unboxing Auch Werttypen (int, struct, enum) sind zu object kompatibel! Boxing Bei der Zuweisung object obj = 3; Java 1.4 Object obj = new Integer(3); wird der Wert 3 in ein Heap-Objekt eingepackt obj 3 Unboxing Bei der Zuweisung int x = (int) obj; int x = ((Integer)obj).intValue(); wird der eingepackte int-Wert wieder ausgepackt 6 Klassen und Vererbung C# Java class A { private int x; public void Foo() {...} public A(int x) { this.x = x; } } class A { private int x; public void Foo() {...} public A(int x) { this.x = x; } } class B : A, I1, I2 { private int y; class B extends A implements I1, I2 { private int y; public int Bar() { ...} public int Bar() { ...} public B(int x, int y) : base(x) { this.y = y; } public B(int x, int y) { super(x); this.y = y; } } } 7 Überschreiben von Methoden C# Java class A { ... public virtual void Foo() { ...} } class A { ... public void Foo() { ...} } class B : A { ... public override void Foo() { base.Foo(); ... } } class B extends A { ... public void Foo() { super.Foo(); ... } } 8 Properties Syntaktische Kurzform für get/set-Methoden class Data { FileStream s; Typ des Properties Name des Properties public string FileName { set { s = new FileStream(value, FileMode.Create); } get { return s.Name; } } "Eingangsparameter" von set } Wird wie ein Feld benutzt ("smart fields") Data d = new Data(); d.FileName = "myFile.txt"; string s = d.FileName; // ruft d.set("myFile.txt") auf // ruft d.get() auf 9 Properties (Fortsetzung) get oder set kann fehlen class Account { long balance; public long Balance { get { return balance; } } } x = account.Balance; account.Balance = ...; // ok // verboten Nutzen von Properties • • • read-only und write-only-Daten möglich. Validierung beim Zugriff möglich. Benutzersicht und Implementierung der Daten können verschieden sein. 10 Indexer Programmierbarer Operator zum Indizieren einer Folge (Collection) class File { FileStream s; Typ des indizierten Ausdrucks Name (immer this) Typ und Name des Indexwerts public int this [int index] { get { s.Seek(index, SeekOrigin.Begin); return s.ReadByte(); } set { s.Seek(index, SeekOrigin.Begin); s.WriteByte((byte)value); } } } Benutzung File f = ...; int x = f[10]; f[10] = 'A'; // ruft f.get(10) // ruft f.set(10, 'A') 11 C# ist oft griffiger als Java C# Java Hashtable tab = new Hashtable(); ... tab["John"] = 123; ... int x = (int) tab["John"]; Hashtable tab = new Hashtable(); ... tab.put("John", new Integer(123)); ... int x = ((Integer) tab.get("John")).intValue(); String s = ...; ... for (int i = 0; i < s.Length; i++) process(s[i]); String s = ..; ... for (int i = 0; i < s.length(); i++) process(s.charAt(i)); foreach (char ch in s) process(ch); 12 Ausnahmebehandlung (Exceptions) C# try { ... ... throw myException; ... } catch (E1 e) { ... } catch (E2) { ... } catch { ... } finally { ... } Java try { ... ... throw myException; ... } catch (E1 e) { ... } catch (E2 e) { ... } catch (Throwable e) { ... } finally { ... } 13 Keine Checked Exceptions in C# C# void Foo() { try { if (...) throw new E1(); else throw new E2(); ... } catch (E1 e) { ... } } Java void Foo() throws E2 { try { if (...) throw new E1(); else throw new E2(); ... } catch (E1 e) { ... } } Keine Checked Exceptions Checked Exceptions Wenn keiner der Rufer E2 abfängt, bricht das Programm mit einem Laufzeitfehler ab. Ausnahmen müssen abgefangen oder mit throws im Methodenkopf spezifiziert werden. 14 Checked Exceptions Pro + Dokumentation für den Programmierer + Zwingt dazu, jeden Fehlerfall zu bedenken Kontra - Mühsam, wenn Ausnahme weitergereicht wird void P() { try { ... Q(); ... } catch (E e) {...} } void Q() throws E { ... R(); ... } void R() throws E { ... S(); ... } void S() throws E { ... throw new E(); } - Verführt zu folgendem "Hack" try { ... } catch (E e) {} Fehler wird verschluckt! 15 Delegate = Methodentyp Deklaration eines Delegate-Typs delegate void Notifier (string sender); // normale Methodensignatur // mit Schlüsselwort delegate Deklaration einer Delegate-Variablen Notifier notify; Zuweisung einer Methode an eine Delegate-Variable void SayHello(string sender) { Console.WriteLine("Hello " + sender); } void SayGoodBye(string sender) { Console.WriteLine("Good bye " + sender); } notify = new Notifier(SayHello); notify = new Notifier(SayGoodBye); Aufruf der Delegate-Variablen notify("Max"); // Aufruf von SayHello("Max") => "Hello Max" 16 Multicast-Delegates Delegate-Variable kann mehrere Werte gleichzeitig aufnehmen Notifier notify; notify = new Notifier(SayHello); notify += new Notifier(SayGoodBye); notify("Max"); // "Hello Max" // "Good bye Max" notify -= new Notifier(SayHello); notify("Max"); // "Good bye Max" 17 Threads C# void P() { ... thread actions ... } Thread t = new Thread(new ThreadStart(P)); t.Start(); Java class MyThread extends Thread { public void run() { ... thread actions ... } } Thread t = new MyThread(); t.start(); • Beliebige Methode kann als Thread gestartet werden • Thread-Aktionen müssen in einer run-Methode stecken • Keine Unterklasse von Thread nötig • Unterklasse von Thread nötig, bzw. Implementierung von Runnable 18 Thread-Synchronisation Java C# class Buffer { int[] data; class Buffer { int[] data; public void Put(int x) { lock(this) { ... } } public void put(int x) { synchronized(this) { ... } } [MethodImpl(MethodImplOptions.Synchronized)] public int Get() { ... } public synchronized int get() { ... } } } Monitor.Wait(this); wait(); Monitor.Pulse(this); Monitor.PulseAll(this); notify(); notifyAll(); 19 Attribute Benutzerdefinierte Informationen über Programmelemente • • • • Können an Typen, Felder, Methoden, etc. angehängt werden. Werden als Metadaten gespeichert. Können zur Laufzeit abgefragt werden. Sind Unterklassen von System.Attribute. Beispiel [Serializable] class C {...} // macht C serialisierbar Mehrfache Attribute zuweisbar [Serializable] [Obsolete] class C {...} [Serializable, Obsolete] class C {...} 20 Beispiel: [Conditional]-Attribut Für bedingte Aufrufe von Methoden #define debug // Präprozessor-Anweisung class C { [Conditional("debug")] static void Assert (bool ok, string errorMsg) { if (!ok) { Console.WriteString(errorMsg); System.Environment.Exit(0); } } static void Main (string[] arg) { Assert(arg.Length > 0, "no arguments specified"); Assert(arg[0] == "...", "invalid argument"); ... } } Assert wird nur aufgerufen, wenn debug definiert wurde. 21 J# - Java unter .NET • Vollständige Java-Syntax (JDK 1.1.4), ähnlich J++ • Delegates wie in C# • Unterstützt die meisten Java-Bibliotheken (nicht RMI, JNI) • Unterstützt die meisten .NET-Bibliotheken (ASP.NET, ADO.NET, Windows Forms) • Kann unter Visual Studio.NET verwendet werden • Erzeugt keine Java-Bytecodes sondern .NET-Assemblies => nicht portabel, keine Applets 22 Was bringt die Zukunft? Generische Typen C# 2.0 Java 1.5 class Stack<T> { void Push(T x) {...} T Pop() {...} ... } class Stack<T> { void Push(T x) {...} T pop() {...} ... } Stack<int> s = new Stack<int>(); ... int x = s.Pop(); Stack<String> s = new Stack<String>(); ... String x = s.pop(); • Erzeugt neue Klasse Stack_int • Keine Casts zur Laufzeit • • • • Erzeugt keine neue Klasse Stack-Elemente als Objects gespeichert Versteckte Casts zur Laufzeit Keine primitiven Typen (int, char, ...) als Typparameter erlaubt! 23 Java 1.5 holt auf ... Boxing / Unboxing Object obj = 3; int x = obj; // kein Cast nötig! in C# Object obj = 3; int x = (int) obj; Enumerationen enum Color {red, blue, green} ... if (color == Color.red) ... enum Color {red, blue, green} ... if (color == Color.red) ... Spezielle for-Schleife ( foreach) for (Object s : collection) System.out.println((String)s); foreach (string s in collection) Console.WriteLine(s); Metadaten ( Attribute) public @interface Author { String name(); } ... @Author(name = "HM") public void foo() {...} public class Author : Attribute { string _name; public string Name { set {_name = value; } } } ... [Author(Name = "HM")] public void Foo() {...} 24 C# 2.0 führt neue Features ein ... Anonyme Methoden delegate void Notifier (string s); ... Notifier var = delegate (string s) { Print("I got an " + s); } Partielle Typen public partial class A { // in Datei X.cs public void Foo() {...} ... } public partial class A { // in Datei Y.cs public void Bar() {...} ... } Iteratoren public class Stack { private int[] data; private int top; public void Push(int x) {...} public int Pop() {...} ... public IEnumerator GetEnumerator() { for (int i = 0; i < top; i++) yield return data[i]; } } Stack stack = new Stack(); ... foreach (int x in stack) Console.WriteLine(x); 25 Zusammenfassung C# mächtiger Java kleiner und einfacher Structs, Referenzparameter, Attribute, ... bequemer und griffiger größere Verbreitung Indexer, Delegates, ... flexibler strikter erlaubt Systemprogrammierung Checked Exceptions, kein Unsafe Code besser unter Windows portabler 26 Danke für Ihre Aufmerksamkeit Folien unter http://dotnet.jku.at Beer, Bringruber, Mössenböck, Wöß: Mössenböck: Die .NET-Technologie Softwareentwicklung mit C# dpunkt.verlag, 2002 dpunkt.verlag, 2003