एक तार से पहले $ का क्या अर्थ है?


251

मैं शब्दशः स्ट्रिंग का उपयोग करने जा रहा था, लेकिन मैंने गलती से $इसके बजाय टाइप किया @

लेकिन कंपाइलर ने मुझे कोई त्रुटि नहीं दी और सफलतापूर्वक संकलित किया।

मैं जानना चाहता हूं कि यह क्या है और यह क्या करता है। मैंने इसके लिए खोज की लेकिन मुझे कुछ नहीं मिला।

हालाँकि यह एक शब्दशः स्ट्रिंग की तरह नहीं है क्योंकि मैं लिख नहीं सकता:

string str = $"text\";

क्या किसी को पता है कि $सी # में स्ट्रिंग के लिए पहले क्या है।

string str = $"text";

मैं विजुअल स्टूडियो 2015 CTP का उपयोग कर रहा हूं।

जवाबों:


419

$के लिए शॉर्ट-हैंड है String.Formatऔर स्ट्रिंग इंटरपोलेशन के साथ प्रयोग किया जाता है, जो C # 6 की एक नई विशेषता है। जैसा कि आपके मामले में उपयोग किया जाता है, यह कुछ भी नहीं करता है, जैसे कि string.Format()कुछ भी नहीं।

यह अपने आप में आता है जब अन्य मूल्यों के संदर्भ में तार बनाने के लिए उपयोग किया जाता है। पहले क्या लिखा जाना था:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = string.Format("{0},{1},{2}", anInt, aBool, aString);

अब बन जाता है:

var anInt = 1;
var aBool = true;
var aString = "3";
var formated = $"{anInt},{aBool},{aString}";

वहाँ भी एक वैकल्पिक - कम अच्छी तरह से जाना जाता है - स्ट्रिंग प्रक्षेप के रूप का उपयोग कर $@ (दो प्रतीकों का क्रम महत्वपूर्ण है)। यह @""स्ट्रिंग की विशेषताओं को आपके पूरे स्ट्रिंग $""की आवश्यकता के बिना स्ट्रिंग प्रक्षेपों का समर्थन करने के लिए मिश्रित करने की अनुमति देता है \\। तो निम्नलिखित दो लाइनें:

var someDir = "a";
Console.WriteLine($@"c:\{someDir}\b\c");

उत्पादन होगा:

c:\a\b\c

29
ध्यान दें कि यह वास्तव में String.Format का उपयोग नहीं कर रहा है, लेकिन एक संकलक-आधारित सुविधा है, न कि रनटाइम।
शाहर प्रीश

2
माइनर ध्यान दें कि मैंने आज सीखा, यदि आप उपयोग करते हैं $@, तो आप "उपयोग करके चरित्र से बचने के लिए मजबूर हैं ""। यह मामला नहीं है जब आप केवल उपयोग करते हैं $
फ्लाटर

3
@ फ़्लैटर का $ प्रतीक से कोई लेना देना नहीं है, हालांकि। यह वैसा ही व्यवहार है जैसा कि $ प्रतीक के अस्तित्व में आने से पहले था।
डेवर्नॉन

2
शब्दशः (@) के क्रम और प्रक्षेप ($) प्रतीक के आदेश के बारे में आपकी बात महत्वपूर्ण होने के कारण, इसे C # 8 में ठीक किया जा रहा है, ताकि आदेश अब मायने नहीं रखेगा। देखें: devsanon.com/uncategorized/…
elkaz

39

यह एक प्रक्षेपित स्ट्रिंग बनाता है ।

से MSDN

तार निर्माण के लिए उपयोग किया जाता है। एक प्रक्षेपित स्ट्रिंग अभिव्यक्ति एक टेम्पलेट स्ट्रिंग की तरह दिखती है जिसमें अभिव्यक्ति होती है। एक प्रक्षेपित स्ट्रिंग अभिव्यक्ति अभिव्यक्तियों के परिणामों के ToString रिप्रेशनेशन के साथ निहित अभिव्यक्तियों को प्रतिस्थापित करके एक स्ट्रिंग बनाती है।

पूर्व:

 var name = "Sam";
 var msg = $"hello, {name}";

 Console.WriteLine(msg); // hello, Sam

आप प्रक्षेपित स्ट्रिंग के भीतर अभिव्यक्तियों का उपयोग कर सकते हैं

 var msg = $"hello, {name.ToLower()}";
 Console.WriteLine(msg); // hello, sam

इसके बारे में अच्छी बात यह है कि आपको मापदंडों के क्रम के बारे में चिंता करने की ज़रूरत नहीं है जैसा कि आप करते हैं String.Format

  var s = String.Format("{0},{1},{2}...{88}",p0,p1,..,p88);

अब यदि आप कुछ मापदंडों को हटाना चाहते हैं तो आपको सभी गणनाओं को अपडेट करना होगा, जो कि अब ऐसा नहीं है।

ध्यान दें कि अच्छा पुराना string.formatअभी भी प्रासंगिक है यदि आप अपने स्वरूपण में सांस्कृतिक जानकारी निर्दिष्ट करना चाहते हैं ।


ध्यान दें कि आप अभी भी $संस्कृति की जानकारी का उपयोग कर सकते हैं और निर्दिष्ट कर सकते हैं यदि आप $सही संस्कृति, उदाहरण के लिए, अभिव्यक्ति के अंदर अपने डेटा को स्ट्रिंग में परिवर्तित करते हैं, जैसे {somevar.ToString(...,[Insert culture info here])}
jrh

18

उदाहरण कोड

public class Person {
    public String firstName { get; set; }
    public String lastName { get; set; }
}

// Instantiate Person
var person = new Person { firstName = "Albert", lastName = "Einstein" };

// We can print fullname of the above person as follows
Console.WriteLine("Full-Name - " + person.firstName + " " + person.lastName);
Console.WriteLine("Full-Name - {0} {1}", person.firstName, person.lastName);
Console.WriteLine($"Full-Name - {person.firstName} {person.lastName}");

उत्पादन

Full-Name - Albert Einstein
Full-Name - Albert Einstein
Full-Name - Albert Einstein

यह इंटरपोलेटेड स्ट्रिंग्स है । आप एक प्रक्षेपित स्ट्रिंग का उपयोग कर सकते हैं कहीं भी आप एक स्ट्रिंग शाब्दिक का उपयोग कर सकते हैं। जब आपका प्रोग्राम चल रहा होता है, तो कोड को प्रक्षेपित स्ट्रिंग शाब्दिक के साथ निष्पादित करता है, कोड प्रक्षेप अभिव्यक्ति का मूल्यांकन करके एक नए स्ट्रिंग शाब्दिक की गणना करता है। यह संगणना प्रत्येक बार कोड को प्रक्षेपित स्ट्रिंग के निष्पादन के साथ होता है।

उदाहरण के बाद एक स्ट्रिंग मान पैदा करता है जहां सभी स्ट्रिंग प्रक्षेप मानों की गणना की गई है। यह अंतिम परिणाम है और टाइप स्ट्रिंग है। डबल घुंघराले ब्रेसिज़ की सभी घटनाएं (“{{“ and “}}”)एकल घुंघराले ब्रेस में बदल जाती हैं।

string text = "World";
var message = $"Hello, {text}";

2 लाइनों के ऊपर निष्पादित करने के बाद, चर messageमें "हैलो, वर्ल्ड" होता है।

Console.WriteLine(message); // Prints Hello, World

संदर्भ - MSDN


10

शांत सुविधा। मैं सिर्फ इस बात पर जोर देना चाहता हूं कि यह स्ट्रिंग से बेहतर क्यों है। यह कुछ लोगों के लिए स्पष्ट नहीं है।

मैंने किसी को पैरामीटर स्ट्रिंग से मिलान करने के लिए "{0} {1} {2}" ऑर्डर स्ट्रिंग पढ़ा। आपको string.format में "{0} {1} {2}" ऑर्डर करने के लिए मजबूर नहीं किया जाता है, आप "{2} {0} {1}" भी कर सकते हैं। हालांकि, यदि आपके पास बहुत सारे पैरामीटर हैं, तो 20 की तरह, आप वास्तव में "{0} {1} {2} ... {19}" स्ट्रिंग को अनुक्रमित करना चाहते हैं। यदि यह एक गड़बड़ गड़बड़ है, तो आपके पास अपने मापदंडों को अस्तर करने के लिए एक कठिन समय होगा।

$ के साथ, आप अपने मापदंडों की गणना किए बिना पैरामीटर इनलाइन जोड़ सकते हैं। यह कोड को पढ़ने और बनाए रखने में बहुत आसान बनाता है।

$ का नकारात्मक पक्ष यह है कि आप स्ट्रिंग में पैरामीटर को आसानी से दोहरा नहीं सकते हैं, आपको इसे टाइप करना होगा। उदाहरण के लिए, यदि आप System.Environment.NewLine टाइप करके थक गए हैं, तो आप string.format ("... {0} ... {0} ... {0}", System.Environment.NewLine) कर सकते हैं, लेकिन, $ में, आपको इसे दोहराना होगा। आप $ "{0}" नहीं कर सकते हैं और इसे string.format को पास कर सकते हैं क्योंकि $ "{0}" रिटर्न "0"।

साइड नोट पर, मैंने एक और नकली टैनिक में एक टिप्पणी पढ़ी है। मैं टिप्पणी नहीं कर सकता, इसलिए, यहाँ यह है। वह उसने कहा

string msg = n + " sheep, " + m + " chickens";

एक से अधिक स्ट्रिंग ऑब्जेक्ट बनाता है। यह वास्तव में सच नहीं है। यदि आप इसे एक पंक्ति में करते हैं, तो यह केवल एक स्ट्रिंग बनाता है और स्ट्रिंग कैश में रखा जाता है।

1) string + string + string + string;
2) string.format()
3) stringBuilder.ToString()
4) $""

वे सभी एक स्ट्रिंग लौटाते हैं और केवल कैश में एक मूल्य बनाते हैं।

दूसरी ओर:

string+= string2;
string+= string2;
string+= string2;
string+= string2;

कैश में 4 भिन्न मान बनाता है क्योंकि 4 ";" हैं।

इस प्रकार, निम्नलिखित की तरह कोड लिखना आसान हो जाएगा, लेकिन कार्लोस मुनोज़ द्वारा सही किए जाने पर आप पांच प्रक्षेपित स्ट्रिंग बनाएंगे:

string msg = $"Hello this is {myName}, " +
  $"My phone number {myPhone}, " +
  $"My email {myEmail}, " +
  $"My address {myAddress}, and " +
  $"My preference {myPreference}.";

यह कैश में एक सिंगल स्ट्रिंग बनाता है जबकि आपके पास कोड पढ़ना बहुत आसान है। मुझे प्रदर्शन के बारे में निश्चित नहीं है, लेकिन, मुझे यकीन है कि एमएस इसे ऑप्टिमाइज़ करेगा यदि पहले से ही ऐसा नहीं कर रहा है।


1
आपका अंतिम उदाहरण गलत है: वास्तव में आप दो तार काट रहे हैं: एक प्रक्षेपित स्ट्रिंग से और दूसरा बाकी तारों से। ध्यान दें कि केवल {myName} वाला ही प्रक्षेपित होता है, बाकी लोग अपेक्षा के अनुरूप काम नहीं करते हैं।
कार्लोस मुनोज़

1
और यदि आप $ 5 स्ट्रिंग्स के लिए $ प्रिपेंड करते हैं तो यह 5 इंटरपोल किए गए स्ट्रिंग्स को अपने स्वयं के साथ बनाता है String.Format()और फिर रनटाइम के साथ कंक्रीटिंग करता है String.Concat। इसलिए यह बेहतर है कि आप इसे कई लाइनों में विभाजित न करें
कार्लोस मुअनोज़

1
आप सही हैं @ कार्ल मुनोज़, मैंने इसे सही किया है। गलती पकड़ने के लिए धन्यवाद।
BoBoDev

8

ध्यान दें कि आप दोनों को मिला सकते हैं, जो बहुत अच्छा है (हालांकि यह थोड़ा अजीब लगता है):

// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");

5
यदि बस आप उस आदेश को तय कर सकते हैं जिसमें आपने टाइप किया था $@या @$। दुर्भाग्य से यह केवल हो सकता है$@
Bauss

2
@ कारण यह समझ में आता है। @परिभाषित करता है कि स्ट्रिंग शाब्दिक का प्रतिनिधित्व कैसे करें। $के लिए एक शॉर्टकट है string.Format। इसे $(@"");
ऐसे समझें

यह वास्तव में एक शॉर्टकट नहीं है string.Format। यह एक ऐसे मूल्य को प्रस्तुत करने के लिए मीठा है, जो पार्स हो जाता है string.Format, इसलिए यह आंशिक रूप से समझ में आता है, लेकिन पूरी तरह से नहीं।
बाउस

3
मैं बस कह रहा हूं कि $मूल रूप से एक फंक्शनल फंक्शन कॉल है, जबकि एक दशमलव शाब्दिक की @तरह, शाब्दिक का हिस्सा है m। इसलिए केवल एक तार्किक क्रम है।
1717

2
मुझे पता है कि यह केवल यहाँ प्रदर्शित करने के लिए था $, लेकिन अधिकतम अनुकूलता के लिए और हार्ड कोडिंग के लिए नहीं कि क्या निर्देशिका विभाजक '/' या '\' है, और अपरिहार्य स्क्रूप से बचने के लिए दोहरी स्लैश या लापता स्लैश का निर्माण करना चाहिए जहाँ पर होना चाहिए एक रहा है, मैं Path.Combine()निर्देशिका और फ़ाइलों के साथ काम करते समय स्ट्रिंग संघनन का उपयोग करने के बजाय उपयोग करने की सलाह देता हूं ।
jrh

6

यह स्ट्रिंग की तुलना में अधिक सुविधाजनक है। पोरमेट और आप यहां भी इंटैलिजेंस का उपयोग कर सकते हैं।

यहां छवि विवरण दर्ज करें

और यहाँ मेरी परीक्षा विधि है:

[TestMethod]
public void StringMethodsTest_DollarSign()
{
    string name = "Forrest";
    string surname = "Gump";
    int year = 3; 
    string sDollarSign = $"My name is {name} {surname} and once I run more than {year} years."; 
    string expectedResult = "My name is Forrest Gump and once I run more than 3 years."; 
    Assert.AreEqual(expectedResult, sDollarSign);
}

6

यह स्ट्रिंग प्रक्षेप को दर्शाता है।

यह आपकी सुरक्षा करेगा क्योंकि यह स्ट्रिंग मूल्यांकन पर संकलन समय सुरक्षा जोड़ रहा है।

अब आपको कोई अपवाद नहीं मिलेगा string.Format("{0}{1}",secondParamIsMissing)


6

निम्नलिखित उदाहरण string.Format()स्वच्छता और पठनीयता के रूप में जहाँ तक प्रक्षेपित स्ट्रिंग्स का उपयोग करने के विभिन्न लाभों पर प्रकाश डालता है। इससे यह भी पता चलता है कि कोड {}किसी अन्य फ़ंक्शन तर्क की तरह मूल्यांकन किया जाता है, जैसे कि अगर string.Format()हम कहा जा रहे हैं।

using System;

public class Example
{
   public static void Main()
   {
      var name = "Horace";
      var age = 34;
      // replaces {name} with the value of name, "Horace"
      var s1 = $"He asked, \"Is your name {name}?\", but didn't wait for a reply.";
      Console.WriteLine(s1);

      // as age is an integer, we can use ":D3" to denote that
      // it should have leading zeroes and be 3 characters long
      // see https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-pad-a-number-with-leading-zeros
      //
      // (age == 1 ? "" : "s") uses the ternary operator to 
      // decide the value used in the placeholder, the same 
      // as if it had been placed as an argument of string.Format
      //
      // finally, it shows that you can actually have quoted strings within strings
      // e.g. $"outer { "inner" } string"
      var s2 = $"{name} is {age:D3} year{(age == 1 ? "" : "s")} old.";
      Console.WriteLine(s2); 
   }
}
// The example displays the following output:
//       He asked, "Is your name Horace?", but didn't wait for a reply.
//       Horace is 034 years old.

6

$ वाक्यविन्यास अच्छा है, लेकिन एक नकारात्मक पहलू के साथ।

यदि आपको एक स्ट्रिंग टेम्पलेट की तरह कुछ चाहिए, जो कि कक्षा स्तर पर क्षेत्र के रूप में घोषित किया जाता है ... एक ही स्थान पर जैसा कि होना चाहिए।

फिर आपको उसी स्तर पर चर घोषित करना होगा ... जो वास्तव में अच्छा नहीं है।

इस तरह की चीजों के लिए स्ट्रिंग.फॉर्मैट सिंटैक्स का उपयोग करना बहुत अच्छा है

class Example1_StringFormat {
 string template = $"{0} - {1}";

 public string FormatExample1() {
   string some1 = "someone";
   return string.Format(template, some1, "inplacesomethingelse");
 }

 public string FormatExample2() {
   string some2 = "someoneelse";
   string thing2 = "somethingelse";
   return string.Format(template, some2, thing2);
 }
}

ग्लोबल्स का उपयोग वास्तव में ठीक नहीं है और इसके अलावा - यह ग्लोबल्स के साथ भी काम नहीं करता है

 static class Example2_Format {
 //must have declaration in same scope
 static string some = "";
 static string thing = "";
 static string template = $"{some} - {thing}";

//This returns " - " and not "someone - something" as you would maybe 
//expect
 public static string FormatExample1() {
   some = "someone";
   thing = "something";
   return template;
 }

//This returns " - " and not "someoneelse- somethingelse" as you would 
//maybe expect
 public static string FormatExample2() {
   some = "someoneelse";
   thing = "somethingelse";
   return template;
 }
}

यह उत्तर महत्वपूर्ण है क्योंकि यह इंगित करता है कि प्रक्षेप तब होता है जब आप $ स्ट्रिंग को "कॉल" करते हैं, न कि जब आप इसे घोषित करते हैं।
dx_over_dt

1
आप वर्ग अंतराल पर अपने प्रक्षेप चर को घोषित करने के विरोधी पैटर्न के बारे में सही हैं, हालांकि यदि वे चर पहले से ही वर्ग गुणों के हैं, तो यह पैटर्न अच्छी तरह से काम करता है।
dx_over_dt

@dx_over_dt आप गलत हैं। घोषित समय में इंटरपोल किए गए तारों का मूल्यांकन किया जाता है। इसलिए नमूना कोड का कोई मतलब नहीं है। इसका संकलन भी नहीं होगा।
नौबेटी

@ नौसैनिक आप सही हैं कि प्रक्षेपित स्ट्रिंग्स के बारे में दोनों का मूल्यांकन उस समय किया जाता है जब वे घोषित किए जाते हैं और उदाहरण_ $ स्वरूप के बारे में संकलन नहीं करते हैं और नमूना कोड के बारे में कोई मतलब नहीं है :) मैंने इसे बेहतर तरीके से समझाने के लिए नमूने को सही किया है।
टॉम

5

मुझे नहीं पता कि यह कैसे काम करता है, लेकिन आप इसका उपयोग अपने मूल्यों को टैब करने के लिए भी कर सकते हैं!

उदाहरण :

Console.WriteLine($"I can tab like {"this !", 5}.");

बेशक, आप इसे "बदल सकते हैं!" किसी भी चर या किसी भी सार्थक के साथ, जैसे आप टैब को भी बदल सकते हैं।


हाँ आप स्ट्रिंग msdn.microsoft.com/en-us/library/dn961160.aspx
M.kazem Akhgary

0

स्ट्रिंग में $ साइन इंटरपोलेशन स्ट्रिंग की परिभाषा के लिए है, जो स्ट्रिंग को प्रक्षेपित करने के लिए C # में एक विशेषता है, एक "ट्रू स्ट्रिंग" है जिसमें इंटरपोल किए गए भाव हो सकते हैं

अधिक जानकारी के लिए यह उत्तर और उदाहरण का स्रोत है: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.