Что означает $ перед строкой?

251

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

Но компилятор не выдал мне ошибку и скомпилировал успешно.

Я хочу знать, что это такое и что оно делает. Я искал это, но я не мог ничего найти.

Однако это не похоже на дословную строку, потому что я не могу написать:

string str = $"text\";

Кто-нибудь знает, что $перед строкой обозначают в C #.

string str = $"text";

Я использую Visual Studio 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
@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}";

После выполнения выше 2 строк, переменная messageсодержит «Hello, World».

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

Ссылка - MSDN

Saveendra Ekanayake
источник
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".

На примечании стороны я прочитал комментарий в другом дублированном tpoic. Я не мог комментировать, так что вот оно. Он сказал, что

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 оптимизирует это, если еще не делает это.

BoBoDev
источник
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.");
marsze
источник
5
Если только вы могли бы решить порядок, в котором вы набрали $@или @$. К сожалению, это может быть только$@
Bauss
2
@Bauss Это имеет смысл. @определяет, как представить строковый литерал. $это ярлык для string.Format. Думайте об этом как$(@"");
марш
Это не совсем быстрый путь 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);
}
GorkemHalulu
источник
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.
Pažout
источник
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 Вы не правы. Интерполированные строки оцениваются во время их объявления. Вот почему пример кода не имеет смысла. Это также не будет компилироваться.
9
@NineBerry Вы правы как в отношении интерполированных строк, которые оцениваются во время их объявления, так и в отношении Example_ $. Формат не компилируется, и в примере кода нет смысла :) Я исправил пример, чтобы объяснить его лучше.
Том
5

Я не знаю, как это работает, но вы также можете использовать его для отображения ваших значений!

Пример :

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

Конечно, вы можете заменить «это!» с любой переменной или чем-то значимым, так же как вы можете изменить вкладку.

Эен Амок
источник
да, вы также можете отформатировать строку msdn.microsoft.com/en-us/library/dn961160.aspx
М.Казем Ахгари
0

знак $ в строке предназначен для определения строки интерполяции, которая является функцией в C #, для интерполяции строки является «истинной строкой», которая может содержать интерполированные выражения

для получения дополнительной информации это источник ответа и пример: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

Том Брэдли
источник