C#/.NET में स्ट्रिंग फॉर्मेट करने के तरीके बहुत हैं और तरह-तरह के हैं: ऑब्जेक्ट को सीधे जोड़ने से लेकर, ओवरराइड किए गए object.ToString() मेथड को कॉल करने से होते हुए, ICustomFormatter के इस्तेमाल तक (इस अभ्यास में इस पर चर्चा नहीं की गई है)।
स्ट्रिंग फॉर्मेट करने के दो सबसे आम तरीके हैं स्ट्रिंग इंटरपोलेशन और String.Format()। StringBuilder (cross-ref-tba) क्लास का इस्तेमाल भी स्ट्रिंग बनाने के लिए किया जा सकता है, जब कई लाइनों जैसी कोई जटिलता शामिल हो।
ToString() का इस्तेमालSystem.Object(), जिससे सभी क्लास और स्ट्रक्चर विरासत में मिलते हैं, में एक ToString() मेथड होता है। उदाहरण के लिए, new DateTime(2019, 5, 23).ToString() "05/23/2019 00:00:00" दिखाएगा (अमेरिकी कल्चर वाले थ्रेड पर - नीचे देखिए)। कुछ स्थितियों में, जैसे स्ट्रिंग जोड़ते समय, यह डिफ़ॉल्ट ToString() मेथड अपने आप कॉल हो जाता है; "" + new DateTime(2019, 5, 23) भी वही नतीजा देता है।
डिफ़ॉल्ट ToString() मेथड के अलावा, जिन टाइपों में फॉर्मेटिंग मायने रखती है, उनमें ऐसे ओवरलोड भी होते हैं जो एक फॉर्मेट स्ट्रिंग या फॉर्मेट प्रोवाइडर लेते हैं। BCL (बेस क्लास लाइब्रेरी) में खास तौर पर ये संख्याएँ, दिनांक, एनम और GUID हैं।
String.Format() एक स्ट्रिंग लेता है (डॉक्युमेंटेशन में इसे कम्पोज़िट फॉर्मेट कहा जाता है), जिसमें तय टेक्स्ट और प्लेसहोल्डर (डॉक्युमेंटेशन में इन्हें फॉर्मेट आइटम कहा जाता है) होते हैं, और साथ में किसी भी संख्या में आर्गुमेंट। जो वैल्यू यह लौटाता है, वह हर फॉर्मेट आइटम को उसके साथ वाले आर्गुमेंट की मदद से हल करती है और हल की गई वैल्यू को तय टेक्स्ट के साथ जोड़ देती है।
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
जहाँ एक ही फॉर्मेट किसी टेम्पलेट की तरह कई एक्सप्रेशन में इस्तेमाल हो रहा हो, या जहाँ फॉर्मेट और जिन एक्सप्रेशन को फॉर्मेट करना है उन्हें एक साथ रखना बहुत बोझिल हो जाए, जैसे [वर्बेटिम स्ट्रिंग][verbatim-strings] के मामले में, वहाँ इंटरपोलेशन की तुलना में Format() बेहतर विकल्प हो सकता है।
इस तरीके को तकनीकी रूप से कम्पोज़िट फॉर्मेटिंग कहा जाता है।
जो मेथड स्ट्रिंग बनाते हैं और कम्पोज़िट फॉर्मेटिंग का फ़ायदा उठाते हैं, उनकी पूरी सूची इस लेख में दी गई है।
इंटरपोलेटेड स्ट्रिंग के आगे $ लगाया जाता है और इनमें ब्रेसिज़ के अंदर लिखे रन-टाइम एक्सप्रेशन होते हैं। फॉर्मेट आइटम का सिंटैक्स इस तरह होता है: $"{<interpolationExpression>[,<alignment>][:<formatString>]}"। इससे आर्गुमेंट की अलग सूची बनाने की ज़रूरत नहीं रहती। नतीजा, काम करने के लिहाज़ से, String.Format() तरीके जैसा ही होता है।
एक्सप्रेशन में स्कोप में मौजूद कुछ भी हो सकता है। अलाइनमेंट उस "फील्ड" की लंबाई होती है जिसमें टेक्स्ट बैठता है। अगर अलाइनमेंट धनात्मक है तो टेक्स्ट के बाईं ओर स्पेस भरकर पैडिंग की जाती है, और अगर ऋणात्मक है तो पैडिंग टेक्स्ट के दाईं ओर की जाती है।
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
ब्रेसिज़ के अंदर का टेक्स्ट, यानी कम्पोज़िट फॉर्मेट में प्लेसहोल्डर और स्ट्रिंग इंटरपोलेशन में इंटरपोलेटेड एक्सप्रेशन, फॉर्मेट आइटम कहलाता है।
एक फॉर्मेट आइटम में अधिकतम 3 हिस्से हो सकते हैं। पहला ज़रूरी एक्सप्रेशन या आर्गुमेंट प्लेसहोल्डर है, जैसा ऊपर के उदाहरण कोड में दिखा है। इसके अलावा एक वैकल्पिक अलाइनमेंट (जो कॉमा "," से शुरू होता है) और एक वैकल्पिक फॉर्मेट स्ट्रिंग (जो कोलन ":" से शुरू होती है) हो सकती है।
{<interpolationExpression>[,<alignment>][:<formatString>]}
अलाइनमेंट उस "फील्ड" की लंबाई बताता है जिसमें टेक्स्ट रखा जाता है, अगर अलाइनमेंट धनात्मक है तो बाईं ओर स्पेस भरकर पैडिंग की जाती है और ऋणात्मक है तो दाईं ओर।
फॉर्मेट स्ट्रिंग यह तय करती है कि आउटपुट टेक्स्ट कैसा दिखेगा, जैसे किसी संख्या में हज़ारों को अलग करने वाले विभाजक लगेंगे या नहीं, या DateTime ऑब्जेक्ट का सिर्फ दिनांक वाला हिस्सा दिखाया जाएगा या नहीं।
नीचे दिया गया कोड DateTime ऑब्जेक्ट के दिनांक वाले हिस्से को दिखाना और एक फ्लोटिंग-पॉइंट संख्या को घातांकीय रूप में दिखाना दर्शाता है।
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
संख्याओं और दिनांक, दोनों के लिए मानक और कस्टम, दोनों तरह की फॉर्मेटिंग मौजूद है। कस्टम और मानक में कोई खास फर्क नहीं है, बस इतना कि आपको फॉर्मेट अक्षरों से अपनी कस्टम फॉर्मेट स्ट्रिंग बनाने का मौका मिलता है। यहाँ "कस्टम" का ICustomFormatter इंटरफ़ेस से कोई लेना-देना नहीं है, जिसका इस्तेमाल अपने खुद के कस्टम फॉर्मेटर बनाते समय किया जाता है।
बेस क्लास लाइब्रेरी (BCL) दो फॉर्मेटर देती है: DateTimeFormatInfo और NumberFormatInfo, और फॉर्मेट स्ट्रिंग के 6 समूह।
फॉर्मेट स्ट्रिंग की अलग-अलग सूचियाँ नीचे दी गई हैं:
Enum और GUID की फॉर्मेट स्ट्रिंग को मानक में गिना जा सकता है। हालाँकि enum और GUID में ऐसे ToString() ओवरलोड हैं जो एक IFormatProvider लेते हैं, यह साफ नहीं है कि उससे कोई फर्क पड़ता है।
लाइब्रेरी में फॉर्मेट स्ट्रिंग में कुछ एकरूपता लाने की कोशिश की गई है (इसके अलावा कि वे स्ट्रिंग के रूप में दर्शाई जाती हैं)। एकरूपता की यह कोशिश मानक स्ट्रिंग में दिखती है। वास्तव में, एक डेवलपर के तौर पर आपको मानक और कस्टम स्ट्रिंग के फर्क की परवाह शायद ही कभी करनी पड़ती है। हालाँकि यह अच्छा विचार है कि अगर आप अपनी क्लास के लिए फॉर्मेटर बना रहे हैं और आपकी क्लास ऐसा माँगती दिखती है, तो मौजूदा मानक स्ट्रिंग को दोहराएँ, फिर भी आप इस फर्क को बेझिझक नज़रअंदाज़ कर सकते हैं।
निष्पादन के हर थ्रेड का एक डिफ़ॉल्ट कल्चर होता है, Thread.CurrentThread.CurrentCulture, जो CultureInfo के एक इंस्टेंस में समाहित रहता है। थ्रेड का कल्चर तय करता है कि दिनांक और संख्याएँ डिफ़ॉल्ट रूप से कैसे फॉर्मेट होंगी, क्षेत्रीय भिन्नताओं को ध्यान में रखते हुए, जैसे ब्रिटेन के पारंपरिक दिनांक फॉर्मेट DD/MM/YYYY और अमेरिका के MM/DD/YYYY का फर्क।
CultureInfo, IFormatProvider इंटरफ़ेस को लागू करता है, जिसे String.Format() के कुछ ओवरलोड को पास किया जा सकता है। इसका इस्तेमाल थ्रेड के कल्चर को बदलने के लिए किया जा सकता है।