String.Format

    • Allgemein
    • .NET (FX) 1.0–2.0

    Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von LaMiy.

      Dieses kleine Tut geht um die String.Format-Methode - jeder kennt sie, keiner liebt sie (ich zumindest nicht).
      Eigentlich eine geniale Methode, man kann damit beliebige und beliebig viele Argumente in einen String stopfen, kann zusätzlichen Text dazwischen-fügen, kann zu jedem Argument zT. unerhört differenzierte Zusatz-Angaben machen, wie es im Einzelnen zu formatieren ist.
      Beispiel:

      VB.NET-Quellcode

      1. Imports Microsoft.VisualBasic.ControlChars ' <- dieser Import importiert praktische String-Konstanten, wie Lf, CrLf, Tab
      2. '...
      3. Dim s = String.Format("Hallo {1}!{0}Es ist jetzt {2:hh:mm} Uhr.{0}Du hast dich um {3} Minuten verspätet!{0}Das kost {3:c}", Lf, TextBox1.Text, Date.Now, 7)
      4. Console.WriteLine(s)
      Ausgabe:

      Quellcode

      1. Hallo Himpelchen!
      2. Es ist jetzt 07:37 Uhr.
      3. Du hast dich um 7 Minuten verspätet!
      4. Das kost 7,00 €

      Das schwierige an String.Format() ist das System des Format-Strings richtig zu verstehen. Also dass die {} Platzhalter der Argumente sind, und auch dass die erste Zahl darin je ein bestimmtes Argument addressiert, ist noch einfach.
      Aber dann wird es etwas verwirrend, auch weil die Syntax so flexibel ist. Und weil manche Zeichen, nämlich , und : an verschiedenen Positionen verschiedene Bedeutung haben.

      Also das Innere der Platzhalter {} - gliedert sich in 3 Abschnitte, wobei die letzten beiden auch weggelassen werden können:
      1. zuerst kommt die Nummer, die das zu formatierende Argument addressiert. diese ist erforderlich
      2. Dann kann ein , folgen, welches den Abschnitt einleitet, der die Spalten-Breite und -Ausrichtung steuert.
        ZB {0,-10}: Das - bestimmt Linksbündigkeit, wird es weggelassen, ist die Spalte rechtsbündig. Die Zahl bestimmt die Spaltenbreite.
      3. Dann kann ein : folgen, welches den typ-spezifischen Abschnitt einleitet.
        ZB {2:hh:mm}: Das hh:mm ist eine Formatierung, die nur für DateTime Gültigkeit hat. Und hier haben wir genau das verwirrende, dass der : verschiedenes bedeutet: Der erste : leitet den typspezifischen Formatierungs-Abschnitt ein, und der zweite : hat eine für DateTime spezifische Bedeutung - naja, dort könnte auch jedes andere Trennzeichen stehen, auch sowas: {2:hh U\hr mm}. Beachte hierbei das \h - das h muss nämlich "escaped" werden, damit es nicht als Stunden-Formatzeichen interpretiert wird - aber wie gesagt: das ist typspezifische Syntax für DateTime, zB bei Double wäre sowas ganz ungültig.

      Also einfach die drei Abschnitte merken:
      1) Argument-Index
      2) nach , => SpaltenDefinition
      3) nach : => TypSpezifika


      Hier noch MSDN-Doku - zunächst String.Format, dann die Typ-Spezifischen Syntaxen:
      String.Format()-Methode Da steht das hier gesagte auch, halt weitschweifiger, und das Abschnitt-Prinzip ist kaum zu verstehen
      Standard-Formate für DateTime - Etwa ein einfaches d gibt bei DateTime den Datum-Anteil aus (ohne ZeitAngabe) und zwar in Kurz-Schreibweise, und entsprechend der Kultur - derlei Zeichen gibts noch einige weitere
      Benutzerdefinierte Formate für DateTime - halt wie gezeigt, Zeichen mit speziellen Bedeutungen, aus denen man sich die Darstellung so baukastenmäßig komponieren kann, etwa: dd-MM-yy - hh:mm:ss
      Standard-Formate für Zahlen - Etwa ein einfaches c stellt eine Zahl als Währungs-Wert dar, kultur-abhängig und mit Nachkommastellen - derlei Zeichen gibts noch einige weitere
      Benutzerdefinierte Formate für Zahlen - ähnlich wie bei DateTime, nur halt für Zahlen, zB #.000 wäre ein baukastenmäßig komponiertes, also benutzerdefiniertes Format
      Standard-Formate für TimeSpan - naja, das Prinzip ist glaub jetzt klar, und gilt auch für TimeSpan: Es gibt vorgefertigte Standard-Formate, und...
      Benutzerdefinierte Formate für TimeSpan - benutzerdefinierte Formate.
      Enumerationsformatzeichenfolgen - Auch Enums kann man etwas formatieren, die können namentlich ausgeschrieben sein, als hex oder dezimal


      Zu den Spezifika ist noch zu sagen, dass diese Syntaxen auch für die ToString()-Methode dieser Typen gelten.
      Also Date.Now.ToString("hh:mm:ss") folgt derselben DateTime-Formatierungs-Syntax, wie String.Format("{0,20:hh:mm:ss}", Date.Now)) - aber nur der Abschnitt nach dem ersten : : hh:mm:ss



      Zum Abschluss noch ein Beispiel mit Spaltenformatierung:

      VB.NET-Quellcode

      1. Dim heute = Date.Today
      2. Console.WriteLine("Verspätungen")
      3. Console.WriteLine("{0,-14}{1,-20}{2,-20}", "Datum", TextBox1.Text, TextBox2.Text)
      4. Console.WriteLine("{0,-14:d}{1,-20}{2,-20}", heute, 7, 3)
      5. Console.WriteLine("{0,-14:d}{1,-20}{2,-20}", heute.AddDays(-1), 0, 4)
      Ausgabe

      Quellcode

      1. Verspätungen
      2. Datum Himpelchen Pimpelchen
      3. 11.09.2015 7 3
      4. 10.09.2015 0 4
      Wie man sieht, unterstützt Console.WriteLine() String-Formatierung ebenfalls (und's gibt noch paar weitere derartig writende Klassen, wie StreamWriter, halt alles was von TextWriter erbt)

      Dieser Beitrag wurde bereits 17 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Seit C#6 gibt es btw das:

      C#-Quellcode

      1. int age = 5;
      2. Debug.Print($"Your brother is {age} years old.");


      Also ein String.Format-Ersatz, mit dem man sich die ganzen Platzhalter spart.
      Gibt da übrigens auch Alignments etc.:

      C#-Quellcode

      1. // Alignment
      2. int age = 5;
      3. Debug.Print($"Your brother is {age, 10} years old.");
      4. // Format
      5. float price = 19.99;
      6. Debug.Print($"This bag costs {price : C2} euros.");
      7. // Konditionale Auswertung
      8. Debug.Print($"This bag costs {price} {price == 1 ? "euro" : "euros"}.");


      Grüße
      #define for for(int z=0;z<2;++z)for // Have fun!
      Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

      Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Trade“ ()

      Man kann sogar Methoden der Platzhalter aufrufen.

      C#-Quellcode

      1. ​var customers = new List<string>() { "Kunde1", "Kunde2", "Kunde3" };
      2. Debug.Print($"Es gibt {(customers.Count())} Kunden.");
      3. int customerCount = customers.Count();
      4. Debug.Print($"Die Liste {(customerCount == 0 ? "ist leer" : ($"hat {(customerCount == 1 ? "einen" : $"{customerCount}")} Eintr{(customerCount == 1 ? "ag" : "äge")}"))}");