lernmoment / community-fragen Goto Github PK
View Code? Open in Web Editor NEWC# Fragen aus der LernMoment Community zum lernen und üben in der LernMoment Community.
License: The Unlicense
C# Fragen aus der LernMoment Community zum lernen und üben in der LernMoment Community.
License: The Unlicense
@suchja Hier meine Antwort zur Frage: <SYN-2: Was bedeutet {0} beim Console.WriteLine?>
Hallo Jan,
da diese meine erste Übungsantwort ist kurz zu meiner Person.
Mein Name ist Erich, ich bin 47 Jahre alt und versuche gerade über ein Fernstudium der SGD zum Informatiker in der Welt der Bits und Bytes Fuß zu fassen.
Anbei meine Antwort zu o. g. Fragestellung als Übung:
Bei dem {0} handelt es sich um einen Platzhalter für die auszugebenden Variablen bzw. einen Ausdruck, welcher nach dem letzten Anführungszeichen durch ein Komma getrennt angegeben wird. Mit der Ziffer 0 wird die Stelle gekennzeichnet, an der die Variable hinter dem Komma angegeben wird (Zählweise beginnt wie so oft bei 0 und nicht bei 1).
Antwort Bonusfrage 1:
Mittels des Zeichen $ kann die Variable auch direkt in der Codezeile innerhalb der {...} angegeben werden.
Meiner Meinung nach, ist darüber der Code besser lesbar und weniger Fehleranfällig.
Beispielcode:
string ersterText = "Zehn";
string zweiterText = "10";
string summe = ersterText + "+" + zweiterText;
//Ausgabe gem. Aufgabe
Console.WriteLine("Das Resultat {0}", summe);
//Allternative Ausgabe (mit String-Interpolation)
Console.WriteLine($"Das Resultat {summe}");
Console.ReadLine();
Antwort Bonusfrage 2:
Das Verfahren mit dem Zeichen $ wird als String-Interpolation bezeichnet.
@suchja Hier meine Antwort zur Frage: TES-1: Wie sollten private Methoden einer Klasse getestet werden?
Da ich mich gerade mit dem Testen beschäftige, versuche ich es mal mit dieser Frage.
Grundsätzlich würde ich sagen, kommt man an die Stelle, eine private Methode testen zu müssen, dann stimmt etwas mit dem Designe nicht. Hätte ich eine öffentliche Methode, in der eine private Methode aufgerufen wird und deren Code nur teilweise, oder gar nicht ausgeführt wird. Stellt sich mir die Frage. Wozu dient dieser Code wenn er nicht aufgerufen wird und warum soll ich diesen testen und nicht löschen? Auch der Compiler würde sich melden, wenn Code geschrieben wird, der nie erreicht wird. Clean Code ist hier das Richtige, das ist meine Meinung dazu. Es gibt da gewisse Prinzipien an denen man sich Orientieren kann.
Unter dem Stichwort Clean Code wird man in jedem Fall fündig werden. Separation of Concerns (SoC) und Single Level of Abstraction (SLA) um nur zwei zu nennen.
Aber zurück zu den Tests, ich habe versucht mit der aktuellen Version von MSTest eine Private Methode zu testen.
Es hat nicht funktioniert, oder ich habe nicht die richtige Funktionalität dafür gefunden.
Denn in einem aktuellen und bekannten Fachbuch zu C#, in dem Kapitel UnitTest, heißt es:
[TestMethod]
public void Test_IsPositive()
{
PrivateObject obj = new PrivateObject(typeof(Calculator));
bool actual = (bool)obj.Invoke("IsPositive", 5);
Assert.IsTrue(actual);
}
Dieses Beispiel bezieht sich auf eine Version des .NET Framework.
Wie das bei anderen Test-Frameworks aussieht, (xUnit, NUnit), weiß ich nicht, dazu fehlt mir noch einiges an Wissen und Erfahrung.
Abschließend kann ich nur sagen, man sollte seinen Code so gestallten, dass man nicht in die Situation kommt, private Methoden testen zu müssen.
@suchja Hier meine Antwort zur Frage: Was bedeutet {0} beim Console.WriteLine?
Das {0}
in Console.WriteLine()
ist ein Formatelement, ein indizierter Platzhalter. Die Zahl zwischen den geschweiften Klammern gibt an, welches Objekt dorthin aufgelöst wird. Die Objekte werden, durch Kommata getrennt, nach der Zeichenfolge angegeben. Dabei hat das erste Objekt nach der Zeichenfolge den Index 0
, der Zweite den Index 1
usw.. Das Ganze heißt Kombinierte Formatierung.
Eine Zweite Methode ein Objekt in einer Zeichenfolge unterzubringen, ist das Objekt direkt zwischen den geschweiften Klammern zu schreiben. Dabei muss vor der Zeichenfolge das Sonderzeichen $
eingefügt werden. Zwischen dem $
und der "Zeichenfolge "
darf kein Leerzeichen sein. Meines Erachtens sollte dieser Syntax bevorzugt werden, da die Lesbarkeit des Quellcodes, vorausgesetzt die Bezeichner der Objekt sind sinnvoll gewählt, wesentlich besser ist. Dies wird dann Zeichenfolgeninterpolation genannt.
Ich möchte noch ein abschließendes Beispiel geben, welches beide Arten von Syntax, bei jeweils gleicher Ausgabe bietet.
Beispiel:
var mitarbeiterName = "Horst Plümm";
var aktuellesGehalt = 3465.85;
Console.WriteLine("Der Mitarbeiter {0} bekommt in diesem Monat {1}€.", mitarbeiterName, aktuellesGehalt);
Console.WriteLine($"Der Mitarbeiter {mitarbeiterName} bekommt in diesem Monat {aktuellesGehalt}€.");
// Dieses Beispiel erzeugt folgende Ausgabe:
// Der Mitarbeiter Horst Plümm bekommt in diesem Monat 3465,85€.
// Der Mitarbeiter Horst Plümm bekommt in diesem Monat 3465,85€.
@suchja Hier meine Antwort zur Frage: Warum hast bei "Das Resultat {0}" die 0 da reingeschrieben mit den Klammern.
Dabei handelt es sich um eine Iteration. Die geschweiften Klammern mit der Zahl darin stehen als eine Art Platzhalter. Am Ende des Strings kann man mit einem Komma den Platzhaltern Werte zuweisen. Wie bei Arrays zählt C# dabei ab dem Platz 0. In diesem Fall wird also die erste Variable eingefügt, die nach dem String angegeben ist. Man kann auch mehrere Werte hinter dem String angeben. Will man diese Werte dann einfügen muss man ihre Position nach dem String angeben. Hat man nach dem String noch drei Variablen angegeben, so kann man die dritte Variable über {2} im String aufrufen.
Bonus Fragen:
Wie könnte man den Inhalt von Console.WriteLine noch schreiben? Ist das deiner Meinung nach besser verständlich?
Man könnte den String in Teilstrings aufteilen und mit dem Plusoperator die Variablen dazwischen setzen. Das geht auf Kosten der flüssigen Lesbarkeit und ist daher nicht so gut verständlich. Das sieht dann so aus:
Console.WriteLine("Das Resultat " + variable);
Wie heißt der Fachbegriff wenn vor den Hochkommata eines string ein $ Zeichen verwendet wird?
Der Fachbegriff heißt Iteration.
@suchja Hier mein bisher erarbeiteter Lösungsansatz zur Frage: WPF3.
Sehr gute Beobachtung und lustiger Zufall! Gerade erst gestern habe ich nach einer Richtlinie dazu gesucht und danach meinen Quellcode überarbeitet.
Nein, es gibt nicht wirklich eine Richtlinie bezüglich der Benennung. Zumindest keine die Microsoft dazu veröffentlicht. Allerdings ist der Ansatz die Steuerelemente mit Kleinbuchstaben zu beginnen der "richtigere"! Letztlich steht ja jeder <Button .../>
im XAML dafür, dass eine Instanz der Klasse Button
im MainWindow
als Attribut angelegt wird. Das kannst du erahnen, wenn du in VisualStudio im Projektmappen-Explorer das MainWindow
soweit aufklappst, dass du Einträge wie Kasten_0_0 : Button
siehst. Obwohl es auch für private
Attribute, bzw. Felder wie es bei Microsoft heißt, keine klare Regel gibt, wird doch in den meisten Fällen mit einem Kleinbuchstaben begonnen. Vergleiche dazu diese Diskussion auf StackOverflow mit den entsprechenden Links zu Microsoft-Seiten.
Fazit: Ich starte mittlerweile auch die Namen mit kleinen Buchstaben. Das einzige was mich wirklich nervt ist, dass beim automatischen Erzeugen von EventHandlern dieser dann auch mit einem Kleinbuchstaben beginnt und ich muss das von Hand wieder beheben. Bestimmt wird die Codegenerierung von VisualStudio das aber bald beheben ;-).
Das Thema Namensgebung und Schreibweise bzw. ganz allgemein Coding Convention ist sehr hitzig diskutiert bei Entwicklern. Es gibt dazu jedoch kein wirkliches richtig oder falsch. Daher gibt es auch nicht die eine richtige Lösung. Eine Antwort sollte immer im Kontext eines Projektes oder einer Firma gesehen werden.
@suchja Hier meine Antwort zur Frage: WPF-1: Wie öffne ich ein Unterfenster?
In WPF sind auch alle Oberflächenelemente (wie z.B. Window
) ganz "normale" Objekte. Daher können auch Instanzen eines Window
im Quellcode angelegt werden. Um nun also aus einem Fenster (nennen wir es MainWindow
) ein anderes Fenster (nennen wir es SubWindow
) zu öffnen, braucht es folgende Schritte:
Window
mit Namen SubWindow
erstellen (z.B. im Projektmappenexplorer
Hinzufügen im Kontextmenü und dann Fenster
wählen) und mit dem gewünschten Inhalt füllen. (Siehe Beispielcode hier)MainWindow
einen Button inkl. Click
-Event und Eventhandler hinzufügen. (Siehe Beispielcode hier)MainWindow
-Quellcode eine Instanz vom SubWindow
erstellen und darauf Show
oder ShowDialog
aufrufen. (siehe Beispielcode hier)Bonus-Info:
Der Unterschied zwischen Show
und ShowDialog
liegt darin, dass das MainWindow
bei der Verwendung von ShowDialog
nicht mehr angesprochen werden kann, bis das SubWindow
wieder geschlossen wurde. Dieses Verhalten bei Fenstern wird auch als modal bezeichnet.
Wird das SubWindow
über Show
geöffnet können beide Fenster unabhängig von einander bedient werden.
Wichtig ist dabei, dass WPF nicht grundsätzlich eine Beziehung zwischen den Fenstern herstellt. D.h. öffnest du ein Unterfenster via Show
und schließt das "Hauptfenster", dann läuft die Anwendung weiter und nur das Unterfenster wird angezeigt. Um dieses zu beheben kann du nach dem Anlegen des Unterfensters eine "Eltern-Kind-Beziehung" zwischen den beiden Fenstern definieren (über die Owner
Eigenschaft - siehe Beispiel). Dann wird beim Schließen des Hauptfensters auch das Unterfenster geschlossen.
Hier meine Antwort zur Frage: Wie sollten private Methoden einer Klasse getestet werden?
Hallo Markus,
eine wirklich eindeutige Antwort zu der Frage gibt es allerdings nicht. Wie du schon vermutet hast gibt es viele Entwickler die der Meinung sind, dass private Methoden nicht getestet werden sollten. Der Hintergrund ist, wie von dir richtig angenommen, dass die privaten Methoden durch die Tests der öffentlichen Methoden mit getestet werden.
Einen guten Dankansatz dabei finde ich, dass du Tests gegen die öffentlichen Methoden schreibst um sicher zu stellen, dass sich bei einer Klasse nach aussen nichts ändert bzw. alles richtig funktioniert. Änderst du nun etwas an der Implementierung dieser Klasse, kannst du mithilfe der vorhandenen Tests sicherstellen, dass sich deine Klasse nach aussen immer noch so verhält wie vor der Änderung. Das setzt natürlich voraus, dass du genügend und die richtigen Tests hast.
Die Verwendung von automatischen Unit-Tests haben unheimlich viel mit "gutem" Design zutun. In diesem Fall würde ich sagen die Notwendigkeit eine private Methode zu testen (z.B. weil sie komplex ist oder es schwierig ist ausreichende Tests der verwendenden öffentlichen Methode zu erstellen) ist ein Indiz, dass du Teile deiner Klasse in eine eigene Klasse extrahieren kannst. Es handelt sich hier wie an vielen Stellen um den Ansatz "Single Responsibility Pattern".
Aus der Praxis kann ich allerdings auch sagen, dass es manchmal wirklich schwierig und zeitaufwendig ist alles optimal für Unit-Tests zu entwicklen. Was auch impliziert, dass ich TDD (Test-Drive-Development) selten so einsetze wie es eigentlich gedacht ist. Das ist jedoch ein Thema an dem ich dringend arbeiten muss, weil ich grundsätzlich die Vorteile von TDD schätze und denke, dass es in vielen Projekten wirklich hilfreich ist. Allerdings braucht es dafür einiges an Erfahrung. Auch sollte man hier berücksichtigen wieviel Sinn es für ein konkretes Projekt macht "alles perfekt" zu haben.
Möchtest du nun doch private Methoden testen, dann gibt es (mit Ausnahme von der .NET Core Variante) in Visual Studio Test eine Klasse mit dem Namen PrivateObject
. Diese erlaubt es dir via Reflection private Methode einer Klasse zu testen. Microsoft hat sich allerdings in .NET Core entschieden diesen Ansatz nicht weiterzuverfolgen, weil er als "falsch" angesehen wird.
Möchtest du zu diesem Thema ins Detail gehen, dann kann ich dir diesen Artikel zum Thema Testpyramide empfehlen (ist allerdings auf Englisch :-(). Ebenfalls auf Englisch, aber ein wirklich tolles Buch ist XUnit Test Patterns von Gerard Meszaros.
Ich hoffe das konnte etwas Licht ins Dunkel bringen.
@suchja Hier meine Antwort zur Frage: <SYN-1: Wie kann ich einen String in ein Char-Array wandeln?>
// Als Erstes wird um eine Eingabe gebeten.
Console.WriteLine("Bitte Text eingeben: ");
// Die Eingabe wird in der Variable "text" vom Typ "string" gespeichert.
string text = Console.ReadLine();
// erzeugen eines char-Array
// "text.Length" gibt die Anzahl der Zeichen in "text" als Zahl zurück
char[] sUD = new char[text.Length];
// erzeugen der Index-Variable um das Array zu befüllen
int index = 0;
// Schleife zum befüllen des Array
// Die foreach-Schleife hat den besser lesbaren Syntax
//und ist weniger Fehleranfällig(Bereichsbasierte Schleife)
foreach (char c in text)
{
sUD[index] = c;
index++;
}
Console.WriteLine();
// Ausgabe des Array in einer Zeile
foreach (char c in sUD)
{
Console.Write(c);
}
Console.WriteLine();
// Ausgabe des Array durch Zeichen pro Zeile
foreach (char c in sUD)
{
Console.WriteLine(c);
}
Console.ReadLine();
@suchja Ich habe da mal eine Frage, ich komme nicht weiter.
Ich weiß auch gar nicht ob ich hier richtig bin. Wenn nicht, dann bitte verschieben oder auch sonst was.
Ich schaue gerade das Tutorial auf YouTube des Ballspiels. Die Oberfläche habe ich fertig, und nun soll ja als erstes das Ereignis des StartStopButton_Click entwickelt werden. Per Doppelklick habe ich auch alles soweit und alles funktioniert.
Aber die Funktion kennt weder die Bezeichnung "Spielplstz" noch die Bezeichnung "Ball". Ich habe da folgende Fehlermeldungen: Der Name "Spielplatz" ist im aktuellen Kontext nicht vorhanden.
Eigentlich hat das ja immer mit den Rechten bzw. Sichtbarkeiten zu tun. Ich sehe aber auch nicht, wo ich da einen Fehler haben könnte.
private void StartStopButton_Click(object sender, RoutedEventArgs e)
{
var mitteX = Spielplatz.ActualWidth / 2;
var mitteY = Spielplatz.ActualHeight / 2;
Canvas.SetLeft(Ball, mitteX);
Canvas.SetTop(Ball, mitteY);
}
<Erkläre hier was dir fehlt zur Beantwortung der Frage>
@suchja Hier meine Antwort zur Frage:
string text = Console.ReadLine();
char[] charArrayOfStringvariableText = new char[text.Length];
for (int i = 0; i < text.Length; i++)
{
charArrayOfStringvariableText[i] = text[i];
}
Console.WriteLine(new string(charArrayOfStringvariableText));
@suchja Hier meine Antwort zur Frage: ALL-1 - Konsolenanwendung von externer Festplatte starten
Ja, es ist möglich.
Wenn es sich um eine Konsolen-App (.NET Core) handelt, kann man den Ordner bin -> Debug -> netcoreapp
auf eine externe Festplatte kopieren und von dort kann das Programm dann auch gestartet werden. Es gibt dabei jedoch ein paar Dinge zu beachten:
Main
Methode gestoppt. Wird eine solche App jedoch per Doppelklick aus dem Datei-Explorer gestartet, dann endet die Ausführung am Ende von Main
. Es kann also sein, dass das Konsolenfenster nur kurz aufflackert und die Ausgabe nicht zusehen ist. Daher macht es auch bei einer .NET Core Konsolen-App Sinn als letzte Zeile in der Main
Methode ein Console.Readline();
einzufügen. Dann bleibt das Konsolenfenster offen bis der Anwender Enter
drückt.Wenn es sich um eine Konsolen-App (.NET Framework) handelt, kann man den Ordner bin -> Debug
auf eine externe Festplatte kopieren und von dort kann das Programm dann auch gestartet werden. Auch hier gilt wieder als Voraussetzung, dass das .NET Framework auf dem ausführenden Rechner installiert ist. Dieses ist üblicherweise der Fall, weil es momentan Bestandteil von Windows ist.
Auch diese Frage von Thomas ist wirklich toll. Insbesondere weil sie gut zu erweitern ist mit weiteren Detailfragen.
Hallo Thomas,
Du hast absolut recht. Ich habe noch nicht erklärt was die {0} bedeutet :-(.
Stell dir {0}
wie ein Platzhalter vor. Du sagst damit dem Compiler, dass der Inhalt der an dieser Stelle stehen soll später kommt. Wenn du dann weiter schaust, siehst du, dass nach dem string
(also nach den 2. Anführungszeichen oben) ein Komma und ein Variablenname folgt (summe
). Der aktuelle Wert dieser Variablen wird nun für den Platzhalter verwendet.
Nun möchtest du vielleicht nicht nur einen Wert in den string
einfügen sondern mehrere. Dafür erlaubt es diese Schreibweise, dass du nach dem string
mehrere Variablenname mit Komma getrennt angibst. Über die Zahl in den geschweiften Klammern gibst du an, an welcher Position die Variable in der Liste der angegebenen Variablen steht.
0
bedeutet in diesem Beispiel also, dass der Wert der ersten Variablen verwendet wird (wir haben ja auch nur eine angegeben ;). Hätten wir jedoch zum Beispiel auch die Variablen ersterText
und zweiterText
nach dem string
angegeben, dann könnte das ganze so aussehen:
string ersterText = "Zehn";
string zweiterText = "10";
string summe = ersterText + "+" + zweiterText;
Console.WriteLine(„Die Summe von {0} und {1} ist nicht {2}. Oder doch?“, ersterText, zweiterText, summe);
Macht das Sinn für dich?
Eine weitere Möglichkeit wäre folgende:
string ersterText = "Zehn";
string zweiterText = "10";
string summe = ersterText + "+" + zweiterText;
Console.WriteLine($"Das Resultat {summe}");
Diese Schreibweise mit dem $
nennt man string-Interpolation. Meiner Meinung nach ist sie wesentlich verständlicher und vor allem pflegeleichter, weil man nicht mehr die Zuordnung zwischen Platzhalter und Liste der Variablen hat.
Mehr zum Thema string-Interpolation findest du in diesem Artikel auf LernMoment.de.
Hier meine Antwort zur Frage: SYN-1
Der einfachste Weg einen string
in ein char[]
zu wandeln ist sicherlich dieser:
string text = "Community Frage";
char[] sUD = text.ToCharArray();
Da es jedoch darum geht zu verstehen wie auf einzelne Zeichen im string
zugegriffen werden kann, hier der eigentliche Quellcode ohne Fehler (darunter folgen ein paar Erklärungen):
string text = Console.ReadLine();
char[] sUD = new char[text.Length];
for (int x = 0; x < text.Length; x++)
{
sUD[x] = text[x];
}
sUD
muss vom Type char
sein und ihr muss ein neues Array vom Typ char
zugewiesen werden. Beim eigentlichen zuweisen der einzelnen Zeichen aus text
an sUD
darf dort nicht wieder der Datentyp angegeben werden. Dieser wurde ja bereits vorher festgelegt. Merke: Eine Variable wird einmalig definiert. Dabei wird der Datentyp festgelegt. Bei Arrays kann der Variable dann ein neues Array mit einer definierten Anzahl von Elementen mithilfe von new
zugewiesen werden. Wenn dem Array einzelne Werte zugewiesen werden, dann brauchst du nur den Namen und die Position angeben (nicht den Datentyp).for
-Schleife war fest auf 8 Werte gesetzt. Gibst du mehr oder weniger Zeichen beim Console.ReadLine
ein, bekommst du einen Fehler, weil du ausserhalb der Grenzen bist. Daher habe ich erst den text
via Console.ReadLine
eingelesen. Damit ist klar wieviele Zeichen es gibt. Nun kann sowohl das char
-Array (sUD
) mit den passenden Anzahl angelegt werden, wie auch die passenden Anzahl in der for
-Schleife verwendet werden.text.Length
) bekommst du die Anzahl der Zeichen zurück und musst dann die for
-Schleife anpassen und x < text.Length
nehmen. Das war jedoch in deiner Frage auch schon soweit korrekt.Den kompletten Quellcode für meine Lösung findest du hier
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.