C-Sharp

From Coders.Bay Wiki
Jump to navigation Jump to search

Dieser Cheatsheet soll dir helfen Java Code leichter in C# Code umzuschreiben. Die Sprachen sind sehr ähnlich aufgebaut, wodurch das leicht möglich ist. Die wichtigste Änderung vorweg. Die geschwungenen Klammern { werden in einer neuen Zeile geschrieben und nicht wie in Java noch in der selben Zeile.

Namenkonventionen[edit]

//Java
KlassenNamenWerdenSoGeschrieben
methodenSo
variablenAuchSo
//C#
KlassenWerdenWieInJavaBenannt
MethodenBeginnenHierGroß
variablenKlein
PropertiesGroß

Primitive Datentypen[edit]

//Java
int x;
char c;
double d;
float f;
boolean b;

//Eigentlich in Java kein Primitiver Datentyp
String s;


//C#
int x;
char c;
double d;
float f;
bool b;

//In C# schon
string s;


Konsolen I/O[edit]

//Java Konsolen Ausgabe
System.out.println("Hello World!");
//C# Konsolen Ausgabe
Console.WriteLine("Hello World!");
Console.Write("Hello World!\n");


//Java Konsolen Eingabe
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
//C# Konsolen Eingabe
string input = Console.ReadLine();


Objektorientierung[edit]

Ein wenig größere Änderungen kommen bei der Objektorientierung. Das Konzept der Getter und Setter dürfte in Java bekannt sein. Das sind eigene Methoden, die Zugriffe auf eine interne Variable von außen ermöglichen.

class Car{
 private float speed;
 
 public float getSpeed(){
  return speed;
 }

 public void setSpeed(float speed){
  this.speed = speed;
 }
}

Das ist sehr viel Code für eine sehr leichte Operation. In C# wurde dies um einiges kürzer gemacht ohne Funktionalität zu verlieren. Nämlich mit Properties.

class Car
{
 public float Speed
 {
  get;set;
 }
}

Beide Codes sind funktionsgleich. Getter und Setter werden jedoch oft dafür verwendet nötige Berechnungen durchzuführen oder Wertegrenzen einer Variable einzuhalten. In Java fügt man dafür einfach bei den schon vorhandenen Methoden die Überprüfungen hinzu. In C# geht das natürlich auch.

class Car
{
 private float speed;
 public float Speed
 {
  get
  {
    return speed;
  }
  set
  {
   if(value < 0)
    value = 0;
   speed = value;
  }
 }
}

Man muss die Property voll definieren. Das heißt eine private Variable zusätzlich zur public Property definieren. Beim Setter fällt das Keyword value auf. In dieser Variable befindet sich der neue Wert. Bei der Verwendung von Properties spielt die Schreibweise jedoch keine Rolle. Dies funktioniert immer wie folgt:

void Main()
{
 Car myCar = new Car();
 myCar.Speed = 150;
 Console.WriteLine(myCar.Speed);
}

C# erkennt wie man die Property Speed verwenden möchte und ruft automatisch entweder die Get oder Set Methode auf. Man kann also wie mit privaten Variablen arbeiten, hat aber zusätzlich die Sicherheit die Getter und Setter bieten.

Eine weitere Möglichkeit die C# bietet ist die Mehrfachvererbung. Heißt das erben von mehr als einer Klasse. In Java ist man hier auf ein Interface und eine Basisklasse beschränkt.

Die Syntax für das Erben wurde ebenfalls geändert. In Java gibt es Unterschiede in der Syntax je nachdem ob man von einem Interface oder einer Klasse erbt.

//Java
class MyClass extends MyBaseClass implements MyInterface { }
//C#
class MyClass : MyBaseClass1, MyBaseClass2, IMyInterface1, IMyInterface2
{}

In C# werden alle Interfaces und Klassen von denen geerbt wird mit Beistrich getrennt hinter einem Doppelpunkt aufgelistet. Es herrscht hier die Namenkonvention, dass Interfaces immer mit einem großen I beginnen um sie von zu erbenden Klassen zu unterscheiden.


Strukturierung[edit]

Ein Java Programm ist in Packages unterteilt die mit dem import Statement eingebunden werden können. In C# ersetzen namespaces die Packages und diese können mit einem using Statement eingebunden werden. Unterschiedliche Namen für das selbe Prinzip also. In Java muss eine Klasse immer in einer File mit selben Namen sein. Somit kann sich auch nur eine richtige Klasse in einer File befinden.

In C# sind Filename und Klassenname komplett getrennt. Es können mehrere Namespaces mit jeweils mehreren Klassen in eine File geschrieben werden. Nur weil man kann sollte man aber in den meisten Fälle trotzdem nicht.


Methoden[edit]

Methoden werden in beiden Sprachen gleich definiert. C# bietet jedoch wieder ein paar mehr Möglichkeiten die manche Probleme vermeiden können. In Java werden alle Parameter "by value" übergeben. In C# grundsätzlich auch, jedoch kann man mit den Schlüsselwörtern "ref" und "out" Parameter sowohl als "by reference" oder auch als Ausgabeparameter markieren.

Bei manchen Methoden wäre es sehr praktisch, wenn man mehrere Werte returnieren könnte. In Java würde man entweder eine neue Klasse oder ein Array zurückgeben. In C# kann man entweder Ausgabeparameter nutzen oder einfach mehrere Werte zurückgeben.

(int, string) returnTwoValues(){
   return (42, "Hello World!");
}
(int, string) twoValues = returnTwoValues();
Console.WriteLine(twoValues.Item1);  // Output = 42
Console.WriteLine(twoValues.Item2);  // Output = "Hello World!

Man ist hier in der Anzahl der Rückgabewerte nicht beschränkt, sollte aber natürlich dieses Feature nur mit Bedacht einsetzen.

Collections[edit]

//Java
int[]
ArrayList<int>
HashSet<int>
HashMap<String, int>
//C#
int[]
List<int>
HashSet<int>
Dictionary<string, int>


In Java funktionieren Arrays grundlegend anders als andere Collections, wie Listen und Maps.

In C# ändert sich das. Zwischen diesen drei Collections sind die einzigen zwei Unterschiede, dass ein Array eine Length hat und die anderen einen Count, und dass der Index Operator [] beim Dictionary keinen Index nimmt sondern einen Key.

int[] array = new int[5]{1,2,3,4,5};
List<int> list = new List<int>();
Dictionary<string, int> dictionary = new Dictionary<string, int>();

list.Add(1);
list.Add(2);
list.Add(3);

dictionary.Add("key1", 4);
dictionary.Add("key2", 5);

Console.WriteLine(array[1]);           // Output = 2
Console.WriteLine(array.Length);       // Output = 5

Console.WriteLine(list[2]);            // Output = 3
Console.WriteLine(list.Count);         // Output = 3

Console.WriteLine(dictionary["key1"]); // Output = 4
Console.WriteLine(dictionary.Count);   // Output = 2

Die ArrayList von Java heißt in C# einfach nur List. Zusätzlich können in C# auch primitive Datentypen für Sets und Maps verwendet werden. (In Java ist ein HashSet<int> fehlerhaft. Ein HashSet<Integer> nicht.)

Der Index Operator [] in C# ist zudem um einiges mächtiger als in Java. Will man zum Beispiel der ersten drei oder die letzten zwei Elemente einer Liste muss man in Java schon mal in die Trickkiste greifen.

In C#

int[] firstThreeElements = array[..3];
int[] lastTwoElements = array[^2..];
foreach(int elem in firstThreeElements)       // Output = 1 2 3
   System.Console.Write(elem + " ");

System.Console.WriteLine();
foreach(int elem in lastTwoElements)          // Output = 4 5
   System.Console.Write(elem + " ");

Die Syntax der foreach Schleife hat sich auch leicht geändert.

Ein weiteres Nischenfeature sind mehrdimensionale Arrays. In Java ist dies über Umwege möglich. Man erstellt einfach ein Array eines Arrays. z.B. int[][]. C# bietet aber wirkliche zweidimensionale Arrays. Mit der Syntax:

int[,] twoDimensionalArray = new int[10,10];


Nützliche Features für das Erstellen und Arbeiten mit Libraries[edit]

Extension Methods[edit]

In der C# Standardbibliothek sind sehr viele Funktionalitäten implementiert. Es konnte aber natürlich nicht alles vorimplementiert werden. Will man z.B. den Median eines int[] herausfinden müsste man in Java das in etwa so schreiben:

int median = calculateMedianOfArray(myIntArray);

An sich ok. Den Mittelwert erhalte ich jedoch so:

var x = Arrays.stream(array).average();

Nicht sehr einheitlich und/oder schön. Um Funktionalität zu schon bestehenden aber einem nicht selber gehörenden Klassen hinzuzufügen, gibt es in C# Extension Methods. Sie werden in einer static class definiert und sind selber static methods. Der erste Parameter der Methode hat davor immer das Stichwort this.

static class Extensions{
   public static int Median(this int[] array){
       return array.OrderBy(i => i).ToList()[((array.Length+1)/2)-1];
   }
}

Das tolle ist nun wie diese Methoden verwendet werden können:

int median = array.Median();
double average = array.Average();

Average() ist eine bereits vorhandene Methode gewesen und Median haben wir selbst zur Funktionalität von int[] hinzugefügt. Trotzdem können wir sie komplett gleich verwenden und der Endnutzer(Der Endnutzer unserer Library) merkt nichts davon. Das Konzept der Extensions Methods spiele bei der Entwicklung von Linq eine große Rolle. Wie Linq funktioniert und was Linq ist kommt später.

Operator Overloading[edit]

In Programmiersprachen gibt es verschiedene Operatoren. Das können die einfachen +,-,*,/ sein, aber auch die Indexklammern [] oder die Aufrufklammern () sind Operatoren. In Java sind deren Funktionalität in Stein gemeißelt und können nicht verändert oder erweitert werden.

Entwickelt man z.B. eine 3D Visualisierungssoftware und arbeitet dabei mit Vektoren und Matrizen muss man diese oft miteinander Multiplizieren oder Addieren. In Java würde das wie folgt aussehen:

myMatrix1.Add(myMatrix2);

Ganz normale ints kann man aber so addieren:

int z = x + y;

Da der + Operator nur Zahlen addieren kann besteht in Java keine Möglichkeit diese Zeile zu schreiben:

Matrix result = myMatrix1 + myMatrix2;

Durch Operator Overloading und C# ist dies möglich. Einen Vektor könnte man z.b. so implementieren:

class Vector{
   public float X { get; set; }
   public float Y { get; set; }
   public float Z { get; set; }
   public Vector(float x, float y, float z){
       X = x;
       Y = y;
       Z = z;
   }

   public static Vector operator+(Vector lhs, Vector rhs){
       return new Vector(lhs.X + rhs.X,lhs.Y + rhs.Y,lhs.Z + rhs.Z);
   }
}

Und anschließend so verwenden:

Vector v1 = new Vector(1,2,3);
Vector v2 = new Vector(4,5,6);
Vector result = v1 + v2;