A stringek formázására sokféle mechanizmus létezik a C#/.NET-ben: az objektumok egyszerű összefűzésétől kezdve a felülírt object.ToString() metódus hívásán át egészen az ICustomFormatter használatáig (ez utóbbit ez a feladat nem tárgyalja).
A stringek formázásának két leggyakoribb mechanizmusa a string-interpoláció és a String.Format(). A StringBuilder (cross-ref-tba) osztály is használható string felépítésére, ha bonyolultabb a helyzet, például több sorról van szó.
ToString() használataA System.Object(), amelytől minden osztály és struct örököl, rendelkezik egy ToString() metódussal. Például a new DateTime(2019, 5, 23).ToString() eredménye „05/23/2019 00:00:00” lesz (amerikai kultúrájú szálon, lásd lentebb). Vannak helyzetek, például a stringek összefűzése, amikor ez az alapértelmezett ToString() metódus implicit módon meghívódhat; a "" + new DateTime(2019, 5, 23) ugyanezt az eredményt adja.
Az alapértelmezett ToString() metódus mellett azoknak a típusoknak, amelyeknél a formázás számít, vannak olyan túlterheléseik, amelyek formázási stringet vagy akár formázásiszolgáltatót fogadnak. A BCL-ben (Base Class Library) ezek különösen a számok, a dátumok, a felsorolások és a GUID-ok.
A String.Format() egy stringet (a dokumentációban összetett formátum) fogad, amely rögzített szövegből és helyőrzőkből (a dokumentációban formázási elemek) áll, valamint változó számú argumentumot. A visszatérési érték minden formázási elemet a hozzá tartozó argumentum felhasználásával old fel, majd a feloldott értékeket a rögzített szöveggel fűzi össze.
string.Format("I had {0} bitcoins on {1}, the day I forgot my password.", 55.5, new DateTime(2010, 2, 25))
// => "I had 55.5 bitcoins on 2/25/2010 00:00:00, the day I forgot my password." - US settings
A Format() jobb választás lehet az interpolációnál, ha a formátumot több kifejezésben használod, afféle sablonként, vagy ha a formátum és a formázandó kifejezések együtt túl nehézkesek, például [szó szerinti stringek][verbatim-strings] esetén.
Ezt a mechanizmust szaknyelven összetett formázásnak nevezik.
A összetett formázást kihasználó, stringet előállító metódusok teljesebb listáját ebben a cikkben találod.
Az interpolált stringek $ előtaggal kezdődnek, és kapcsos zárójelek közé zárt futásidejű kifejezéseket tartalmaznak. A formázási elem szintaxisa a következő: $"{<interpolationExpression>[,<alignment>][:<formatString>]}". Ezzel feleslegessé válik az argumentumok külön listája. Az eredmény funkcionálisan egyenértékű a String.Format() mechanizmusával.
A kifejezés bármit tartalmazhat, ami a scope-ban van. Az igazítás annak a „mezőnek” a hossza, amelyben a szöveg elhelyezkedik. Ha az igazítás pozitív, a szöveg balról kap szóközöket, ha pedig negatív, akkor a szövegtől jobbra töltődik ki.
var loadsOf = 55.5;
var thatDay = new DateTime(2010, 2, 25);
$"I had {loadsOf} bitcoins on {thatDay}, the day I forgot my password."
// => "I had 55.5 bitcoins on 2/25/2010 00:00:00, the day I forgot my password." - US settings
A kapcsos zárójelek közötti szöveget, azaz az összetett formátum esetében a helyőrzőket, a string-interpoláció esetében pedig az interpolált kifejezéseket formázási elemnek nevezzük.
Egy formázási elem legfeljebb három részből állhat. Az első a kötelező kifejezés vagy argumentumhelyőrző, ahogy a fenti példakódban is látható. Emellett van egy opcionális igazítás (amit egy vessző, „,” vezet be) és egy opcionális formázási string (amit egy kettőspont, „:” vezet be).
{<interpolationExpression>[,<alignment>][:<formatString>]}
Az igazítás megadja annak a „mezőnek” a hosszát, amelyben a szöveg elhelyezkedik; pozitív igazítás esetén balról, negatív esetén jobbról töltődik ki szóközökkel.
A formázási string a szöveges kimenet alakját határozza meg, például azt, hogy egy számnál legyenek-e ezreselválasztók, vagy hogy egy DateTime objektumnak csak a dátumrésze jelenjen-e meg.
A következő kód egy DateTime objektum dátumrészének és egy lebegőpontos számnak az exponenciális alakban való megjelenítését mutatja be.
var loadsOf = 55.5;
var thatDay = new DateTime(2010, 2, 25);
$"I had {loadsOf:E} bitcoins on {thatDay:d}, the day I forgot my password."
// => I had 5.550000E+001 bitcoins on 02/25/2010, the day I forgot my password. - US settings
string.Format(
"I had {0:E} bitcoins on {1:d}, the day I forgot my password.",
loadsOf, thatDay)
// => I had 5.550000E+001 bitcoins on 02/25/2010, the day I forgot my password. - US settings
A számokhoz és a dátumokhoz egyaránt létezik szabványos és egyéni formázás. Nincs lényegi különbség az egyéni és a szabványos között, azon kívül, hogy az egyéni formázási stringeket formázási karakterekből állíthatod össze. Az „egyéni” ebben az összefüggésben semmi köze nincs az ICustomFormatter felülethez, amelyet saját egyéni formázók fejlesztésekor használsz.
A Base Class Library (BCL) két formázót biztosít: a DateTimeFormatInfo és a NumberFormatInfo osztályt, valamint hat csoportba sorolható formázási stringet.
A formázási stringek különféle listái az alábbiak:
Az Enum és a GUID formázási stringjei a szabványos kategóriába sorolhatók. Bár az enum és a GUID rendelkezik olyan ToString() túlterhelésekkel, amelyek IFormatProvider-t fogadnak, nem világos, hogy annak bármi hatása van.
A könyvtár megpróbál némi következetességet vinni a formázási stringekbe (azon túl, hogy stringként vannak reprezentálva). Ez a következetességre való törekvés a szabványos stringekben érhető tetten. A gyakorlatban fejlesztőként ritkán törődsz a szabványos és az egyéni stringek közötti különbséggel. Bár jó ötlet, ha saját osztályaidhoz formázókat készítesz, hogy a meglévő szabványos stringeket kövesd, amennyiben erre az osztályaid igényt tartanak, a különbséget nyugodtan figyelmen kívül hagyhatod.
Minden végrehajtási szálnak van egy alapértelmezett kultúrája, a Thread.CurrentThread.CurrentCulture, amelyet a CultureInfo egy példánya foglal magába. A szál kultúrája határozza meg, hogyan formázódnak alapértelmezés szerint a dátumok és a számok a regionális eltérések figyelembevételével, például az Egyesült Királyság DD/MM/YYYY és az Egyesült Államok MM/DD/YYYY szokásos dátumformátuma közötti különbség esetén.
A CultureInfo megvalósítja az IFormatProvider felületet, amely átadható a String.Format() bizonyos túlterheléseinek. Ezzel felül lehet bírálni a szál kultúráját.