Zugriffs-Ebenen von Membern Mit Zugriffsebenen gibt man an von welchen Stellen im Code auf Elemente zugegriffen werden kann. Dient für die überschaubarkeit und sicherheit des Codes. Public -> Keine Zugriffseinschränkung Private -> Zugriff auf die Klasse beschränkt Protected -> Zugriff auf Klasse und davon abgeleitete Typen beschränkt Internal -> Zugriff auf die Assembly beschränkt Protected Internal -> Zugriff auf die aktuelle Assembly oder die von der enthaltenen Klasse abgeleiteten Typen beschränkt ____________________________________________________________________________ Werte- und Referenztypen Wertetypen sind die primitiven Datentypen (integer, float), Structs und Enums Referenztypen sind Strings, Arrays und Klassen Unterschied liegt in der Art und Weise wie die Werte gespeichert werden Wertetypen -> Werden auf dem Stack gespeichert Referenztypen -> Werden auf dem Heap gespeichert Stack ist ein bereich des RAMs. Speicher ist sehr effizient und schnell Heap ist ein nicht gut strukturierter bereich des RAMs, weniger effizient. Speicher muss wieder freigegeben werden wenn nicht mehr benötigt. Referenztypen belasten den Speicher mehr, muss vom Garbage-Collector freigegeben werden. Wertetypen enthalten immer den tatsächlichen Wert Referenztypen enthalten nur einen Zeiger/Pointer mit der Referenz auf das Objekt ____________________________________________________________________________ Konstruktor Der Konstruktor ist die erste Methode die in einem Objekt aufgerufen wird Er wird dazu verwendet Eigenschaften und Variablen zu initialisieren Wird mit dem "new" Schlüsselwort eingeleitet, wird bei der erstellung eines Objekts aufgerufen Person person1 = new Person(); Ihm können auch Parameter übergeben werden Person person1 = new Person("Sabine", "Müller", 34); Konstruktor Definition Muss nicht selbst definiert werden, wenn man diesen nicht braucht. Es wird ein leerer Konstruktor automatisch erzeugt, sollte kein eigener definiert werden class Person { //Eigenschaften public string Vorname {get; set;} public string Nachname {get; set;} public int Alter {get; set;} //Konstruktor public Person(string vorname, string nachname, int alter){ Vorname = vorname; Nachname = nachname; Alter = alter; } } Schnittstellen/Interfaces Eine Klasse, die eine Schnittstelle implementiert, muss alle vorgegebenen Member enthalten. Eine Schnittstelle kann folgende Dinge vorschreiben: -Methoden -Eigenschaften -Ereignisse (Events) -Indexer Die eigentliche Funktionalität der Member wird in der Klasse selbst codiert. interface ITier { //Eigenschaften int Alter {get; set;} string Geschlecht {get; set;} //Methoden void Essen(); void Trinken(); } class Löwe : ITier { //Eigenschaften //Methoden } Abstrakte Klassen und Methoden Eine abstrakte Klasse ist eine nicht instanziierbare Klasse, die nur dazu dient geerbt zu werden. Schnittstellen können Member nur vorgeben, während abstrakte Klasse auch tatsächlichen Code enthalten können. Man verwendet abstrakte Klassen auch als Basisklassen. Polymorphismus Statische Polymorphie Mit der statischen Polymorphie ist das Überladen von Methoden gemeint. Dynamische Polymorphie Mit der dynamischen Polymorphie ist das Überschreiben von abstrakten Methoden gemeint. Hierfür kann auch das Schlüsselwort "virtual" verwendet werden. Structs Ein Struct-Typ ist ein Typ in C#, welcher dazu verwendet wird, zusammengehörende Variablen zu gruppieren, um somit kompakte Objekte darzustellen. struct Point { public int x; public int y; } Strukturen sind eine speicherfreundliche "Alternative" zu Klassen, da sie Wertetypen sind und somit auf dem Stack-Speicher verwaltet werden. Ein Struct ist nicht dasselbe wie eine Klasse! (Klasse = Referenztyp, Struct = Wertetyp). Enums Mit Enums können wir unsere eigenen Datentypen definieren. Sie sind eine Sammlung aus Konstanten auf die man einzenln über den Enum zugreifen kann. enum Himmelsrichtung { Nord = 0, Ost = 1, Süd = 2, West = 3 } static void Main(string[] args) { Himmelsrichtung richtung = Himmelsrichtung.Nord; Console.WriteLine(richtung); //OUTPUT: "Nord" Console.WriteLine((int)richtung); //OUTPUT: "0" } Collections Collections sind Klassen, welche das Speichern von mehreren Werten on einem Objekt ermöglichen (ähnlich wie bei Arrays). Sie sind flexibler als Arrays, da ihre Größe nicht beim Kompilieren feststehen muss. -Arrays haben eine statische Grüße -Collections haben eine dynamische Größe -Lists - ähnelt dem Array am meisten, gleiche Funktion nur flexibler und dynamisch, Größe passt sich an. //Erstelle die Liste List<string> namensListe = new List<string>(); //Alternativ List<string> namensListe = new List<string>() { "Alina", "Hendrik", "Janek", "Isabell" }; //Füge Werte zur Liste hinzu namensListe.Add("Janek"); namensListe.Add("Hendrik"); namensListe.Add("Sandra"); //Werte löschen namensListe.Remove("Janek"); //Index löschen namensListe.RemoveAt(2); //Lese die Werte per Schleife aus foreach(string name in namensListe) { Console.WriteLine(name); } Stacks Stacks sind eine sehr einfache Art von Collection, welche man mit einem Stapel Karten vergleichen kann. Stacks haben dabei 3 wichtige Methoden: -Push() -> Zum Hinzufügen von Werten auf den Stapel. -Pop() -> Gibt den obersten Wert auf dem Stapel zurück und löscht ihn dann. -Peek() -> Gibt den obersten Wert auf dem Stapel zurück ohne ihn zu löschen. Der oberste Wert auf dem Stapel ist immer der Wert, der zuletzt hinzugefügt wurde. //Stack erstellen Stack<int> numberStack = new Stack<int>(); //Werte hinzufügen numberStack.Push(1); numberStack.Push(2); numberStack.Push(3); //Obersten Wert lesen und löschen Console.WriteLine(numberStack.Pop()); //OUTPUT: 3 Console.WriteLine(numberStack.Pop()); //OUTPUT: 2 //Obersten Wert lesen Console.WriteLine(numberStack.Peek()); //OUTPUT: 1 Console.WriteLine(numberStack.Peek()); //OUTPUT: 1 Queues Queues sind eine Datenstruktur welche man mit einer Warteschlange vergleichen kann. Die Queue-Klasse enthält 3 wichtige Methoden: -Enqueue() -> Zum hinzufügen eines Wertes zur Warteschlange. -Dequeue() -> Zum lesen und löschen des ersten Wertes in der Warteschlange. -Peek() -> Zum lesen des ersten Wertes ohne ihn zu löschen. Beim lesen wird immer der Wert zurückgegeben der am frühesten hinzugefügt wurde! //Queue erstellen Queue<string> personQueue new Queue<string>(); //Werte hinzufügen personQueue.Enqueue("Peter"); personQueue.Enqueue("Alina"); personQueue.Enqueue("Sandra"); personQueue.Enqueue("Sabrina"); //Ersten Wert lesen und löschen Console.WriteLine(personQueue.Dequeue()); //OUTPUT: Peter Console.WriteLine(personQueue.Dequeue()); //OUTPUT: Alina Console.WriteLine(personQueue.Dequeue());//OUTPUT: Sandra //Ersten Wert lesen Console.WriteLine(personQueue.Peek()); //OUTPUT: Sabrina Console.WriteLine(personQueue.Peek()); //OUTPUT: Sabrina Dictionaries Dictionaries sind eine Datenstruktur, welche man mit einem Wörterbuch vergleichen kann. Die Werte die darin gespeichert werden, bestehen aus einem Key und einem Value. Key und Value können dabei von einem beliebigen Datentyp sein. //Dictionary erstellen Dictionary<int, string> kunden = new Dictionary<int, string>(); //Werte hinzufügen kunden.Add(1000, "Sebastian"); kunden.Add(1001, "Alina"); kunden.Add(1002, "Franz"); kunden.Add(1003, "Peter"); //Werte löschen kunden.Remove(1003); //Zusätzliche Logik um Fehler bei Abfrage von Fehlerhaften Key Werten zu verhindern if (kunden.ContainsKey(1003)){ Console.WriteLine(kunden[1003]); } //Werte Lesen Console.WriteLine(kunden[1002]); //OUTPUT: "Franz" //Dictionaries mit Schleifen durchlaufen foreach(KeyValuePair<int, string> kundenInfo in kunden) { Console.WriteLine(kundenInfo.Key, kundenInfo.Value); } Generics In der Programmierung dienen Variablen als Platzhalter für Werte. Generics dienen als Platzhalter für Datentypen. Generics kommen dann zum Einsatz, wenn man zum Zeitpunkt der Entwicklung noch nicht ganz genau weiß, welchen Datentypen man für eine Varible im Code verwenden möchte. //Generic T erstellen class Wertebehälter<T> { //Eigenschaft vom typ "T" erstellen, dient als Platzhalter //Der Datentyp wird erst bei der Erstellung eines Objektes festgelegt public T MeinWert { get; set; } public Wertebehälter(T wert) { MeinWert = wert; } public void WertAusgabe() { Console.WriteLine(MeinWert.ToString()); } } static void Main(string[] args) { //Der Datentyp "string" wird dem Platzhalter zugewiesen Wertebehälter<string> behälter = new Wertebehälter<string>("Janek"); behälter.WertAusgabe(); //OUTPUT: "Janek" } Delegaten Ein Delegat ist ein Funktionszeiger. Er stellt einen Typen dar, in welchen man die Referenz zu einer Methode speichern kann. Delegaten ermöglichen also das Speichern von Methodenreferenzen in einer Variable, über welche man die Methode dann jederzeit aufrufen kann! Bei der Definition des Delegaten wird der Rückgabetyp und die Methoden-Signatur angegeben. Um eine Methode in einen Delegaten zu schreiben muss diese mit der Delegaten-Definition kompatibel sein. //Delegaten definieren public delegate double Rechenoperation(double x, double y); //Methode erstellen die kompatibel ist mit der Definition der Delegate static double Addition(double x, double y) { return x+y; } //Methodenreferenz wird in die Delegate gespeichert static void Main(string[] args) { Rechenoperation rechenoperation = new Rechenoperation(Addition); double ergebnis = rechenoperation(10,5); } Man verwendet Delegaten dann, wenn zur Laufzeit entschieden werden muss, welche Methode ausgeführt werden soll. Mit Delegaten kann man Methoden definieren, die andere Methoden als Parameter annehmen und intern aufrufen können. Try-Catch Mit Try-Catch kann man Fehler zur Laufzeit abfangen und auf diese reagieren. Das Konstrukt besteht aus mindestens zwei zusammenhängenden Code-Blöcken. In den Try Block kommt der Code hinein, der einen Fehler auslösen könnte. In den Catch Block kommt der Code hinein, mit welchen auf einen eventuellen Fehler reagiert wird. Im Catch Block können wichtige Daten noch abgespeichert werden oder es kann zurück zum Anfang der Fehlerauslösenden Operation gesprungen werden. try { int[] zahlen = new int[3]; zahlen[0] = 0; zahlen[1] = 1; zahlen[2] = 2; zahlen[3] = 3; } catch (InddexOutOfRangeException ex) { Console.WriteLine(ex.Message); Console.WriteLine("Du hast zu viele Indizes befüllt!"); } catch (Exception ex) { Console.WriteLine(ex.Message); } Die Exceptions müssen der Reihe nach immer allgemeiner werden. Der Finally-Block kann als letzter Block an ein Try-Catch-Konstrukt angehängt werden. Der sich im Finally-Block befindliche Code wird IMMER ausgelöst werden, egal ob eine Exception ausgelöst wurde oder nicht. Er wird normalerweise dazu verwendet, um fremde Ressourcen vor dem Verlassen einer Methode wieder freizugeben(Datenbankverbindungen, Datenströme, usw...) static void WriteToFile() { try { //Schreibe auf eine Datei } catch (Exception ex) { //Speichere bereits gesammelte Daten //Informiere den User über den Fehler return; //Beende die Methode } finally { //Trenne die Verbingung zur Datei //Gebe die fremden Ressource wieder frei } //Schreibe Daten in eine Log-Datei } Math-Klasse Häufig verwendete Methoden: -Abs(x) -> "Absolute" Gibt einen Wert in positiv zurück. -Sign(x) -> "Signum" Gibt entweder -1, 0 oder 1 zurück. -Pow(x) -> "Power of X" Potenziert einen Wert. -Sqrt(x) -> "Square Root" Quadratwurzel -Round(x,y) -> Runden auf Nachkommastellen -Ceiling(x) -> Aufrunden auf Ganzzahl -Floor(x) -> Abrunden auf Ganzzahl Die Math-Klasse stellt neben den Methoden auch zwei Konstanten zur Verfügung: PI -> Das Verhältnis eines Kreisumfangs zum Durchmesser E -> Die Basis des natürlichen Logarithmus Random-Klasse Ist eine Klasse, die das erzeugen von zufälligen Zahlen ermöglicht. //Erzeuge Random Objekt Random rnd = new Random(); //Generiere zufällige Zahl zwischen 1 und 3 int zahl = rnd.Next(1, 4); //Gebe die Zahl aus Console.WriteLine(zahl); Die Klasse stellt 3 relevante Methoden für die Erzeugung von zufälligen Werten bereit: Random.Next() -> Gibt eine zufällige Ganzzahl zurück oder eine Zufallszahl in einem Bereich Random.NextBytes() -> Befüllt ein ByteArray mit Zufallszahlen Random.NextDouble() -> Gibt eine zufällige Zahl von 0.0 bis 1.0 zurück System.IO Ist ein Namespace welcher Klassen für die Arbeit mit Dateien, Verzeichnissen und Datenströmen bereitstellt. Sein Aufgabenbereich kann man in 2 Kategorien aufteilen: 1. Arbeit mit Dateien und Verzeichnissen 2. Datentransport mithilfe von Streams Wichtige Klassen: -Directory und DirectoryInfo -> Zum Arbeiten mit Verzeichnissen -File und FileInfo -> Zum Arbeiten mit Dateien -Path -> Zum Arbeiten mit Pfaden -Stream, FileStream, StreamReader, StreamWriter -> Klassen für Datenströme Directory/DirectoryInfo Sie ermöglichen das Erstellen/Verschieben und Auflisten von Verzeichnissen. Die Klassen haben Eigenschaften welche Informationen über das Verzeichnis enthalten. Eigenschaften Name -> Name des Verzeichnisses FullName -> Voller Name (kompletter Pfad) des Verzeichnisses CreationTime -> Zeitpunkt der Erstellung des Verzeichnisses Exists -> Gibt an ob das Verzeichnis existiert Methoden Create() -> Erstellt ein Verzeichnis CreateSubdirectory() -> Erstellt ein Unterverzeichnis Delete() -> Löscht das Verzeichnis und seine Dateien/Unterverzeichnisse GetDirectories() -> Gibt die Unterverzeichnisse des aktuellen Verzeichnisses zurück GetFiles() -> Gibt eine Dateiliste des aktuellen Verzeichnisses zurück Refresh() -> Aktualisiert den Zustand des Objekts File/FileInfo Sie stellen Eigenschaften und Methoden zum Erstellen, Kopieren, Löschen, Verschieben und Öffnen von Dateien bereit. Eigenschaften Attributes -> Ruft die Attribute der Datei ab (z.B) ReadOnly Name -> Gibt den Namen der Datei zurück FullName -> Gibt den ganzen Pfad der Datei zurück Extension ->Gibt die Dateienendung zurück (.txt, .png, .mp3, usw) Length -> Ruft die Größe in Byte ab Exists -> Gibt an ob die Datei existiert Methoden Create -> Erstellt eine Datei Delete() -> Löscht eine Datei unwiederruflich AppendText() -> Erstellt einen Streamwriter, der der Datei einen Text anfügt MoveTo() -> Zum verschieben oder umbenennen von Dateien Encrypt() -> Verschlüsselt eine Datei Decrypt() -> Entschlüsselt eine Datei Steams Ein Stream ermöglicht den Transport von Daten zu und von einer Datenquelle. Zu diesen Datenquellen gehören z.B.: -Dateien (FileStream) -Der Speicher (MemoryStream) -Ein Netzwerk (NetworkStream) All diese Stream-Klassen erben von der Abstrakten Basisklasse "Stream". Helfer Klassen: Für die Arbeit mit Streams gibt es Helfer-Klassen, welche das Umwandeln der Bytes in andere Formate automatisch erledigen. -StreamReader -> Zum lesen von Streams -StreamWriter -> Zum schreiben auf Streams Diese Klassen erzeugen automatisch einen FileStream mit dem gearbeitet wird. Es ist also nur die Erzeugung eines Objektes der Helferklassen nötig.
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter