Що означає $ перед рядком?


251

Я збирався використовувати дослівний рядок, але я помилково набрав $замість @.

Але компілятор не видав мені жодної помилки і склав успішно.

Я хочу знати, що це таке і що робить. Я шукав його, але нічого не міг знайти.

Однак це не схоже на дослівний рядок, тому що я не можу писати:

string str = $"text\";

Хтось знає, що $перед рядком стоять у C #.

string str = $"text";

Я використовую CTP Visual studio 2015.

Відповіді:


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
Незначна зауваження, що я дізнався сьогодні, якщо ви користуєтеся $@, то ви змушені уникати "персонажа, використовуючи "". Це не той випадок, коли ви тільки використовуєте $.
Flater

3
@Flater Це не має нічого спільного з символом $. Це та сама поведінка, що і до існування символу $.
BVernon

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}";

Після виконання вище двох рядків змінна messageмістить "Привіт, світ".

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

Довідка - MSDN


10

Класна функція. Я просто хочу зазначити акцент на тому, чому це краще, ніж string.format, якщо це деяким людям не видно.

Я читав, хто говорить, що замовити string.format до "{0} {1} {2}", щоб відповідати параметрам. Ви не змушені замовляти "{0} {1} {2}" у string.format, ви також можете робити "{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}.";

Це створює одну єдину рядок у кеші, тоді як у вас дуже легко читати код. Я не впевнений у роботі, але впевнений, що MS оптимізуватиме її, якщо цього ще не зробить.


1
Ваш останній приклад неправильний: насправді ви вводите дві струни: одну з інтерпольованої рядки, а іншу з решти рядків. Зауважте, що лише той із {myName} є інтерпольованим, інші не працюють, як очікувалося.
Карлос Муньос

1
І якщо ви додаєте $ до 5 рядків, то тоді створюється 5 інтерпольованих рядків, кожна з яких є власною, String.Format()а потім об'єднується під час виконання з String.Concat. Тож краще, щоб ви не розділили його на кілька рядків
Карлос Муньос

1
Ви праві @Carlos Muñoz, я це виправив. Дякуємо за помилку.
BoBoDev

8

Зауважте, що ви також можете комбінувати два, що досить круто (хоча це виглядає трохи дивно):

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

5
Якщо ви просто можете вирішити порядок, в якому ви ввели $@або @$. На жаль, це може бути лише$@
Bauss

2
@Bauss Це має сенс. @визначає, як представити літеральний рядок. $- це ярлик для string.Format. Подумайте про це$(@"");
marsze

Це насправді не ярлик для string.Format. Це подає значення, яке розбирається на значення a string.Format, тому воно частково має сенс, але не повністю.
Баусс

3
Я просто кажу, що $це в основному неявний функціональний виклик, тоді як він @є частиною буквального, як і mдесятковий буквальний. Тому існує лише один логічний порядок.
марш

2
Я знаю, що це було здебільшого лише для того, щоб продемонструвати $, але задля максимальної сумісності та не важкого кодування, чи є роздільник каталогів '/' чи '\', а також уникнути неминучого накручування, що спричинить подвійну косу рису або пропущену косу рису там, де має бути були одним, я рекомендую використовувати Path.Combine()замість строкових конкатенацій під час роботи з каталогами та файлами.
jrh

6

Це зручніше, ніж string.Format, і ви можете використовувати intellisense і тут.

введіть тут опис зображення

І ось мій метод тестування:

[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

$ синтаксис приємний, але з одним недоліком.

Якщо вам потрібно щось на зразок шаблону рядків, який оголошується на рівні класу як поле ... ну в одному місці, як це має бути.

Тоді ви повинні оголосити змінні на одному рівні ... що насправді не круто.

Набагато приємніше використовувати синтаксис string.Format для подібних речей

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 Ви неправі. Інтерпольовані рядки оцінюються під час їх декларування. Ось чому зразок коду не має сенсу. Він також не складеться.
NineBerry

@NineBerry Ви вірні, як інтерпольовані рядки оцінюються під час їх декларування, і про Example_ $ Format не збирається, а про зразок коду не має сенсу :) Я виправив зразок, щоб пояснити його краще.
Том

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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.