文字列の前の$はどういう意味ですか?


250

逐語的文字列を使用するつもりでしたが、の$代わりに誤って入力しました@

しかし、コンパイラはエラーを出さず、コンパイルに成功しました。

それが何で、何をしているのか知りたい。探しましたが何も見つかりませんでした。

しかし、私は書くことができないので、それは逐語的な文字列のようではありません:

string str = $"text\";

$文字列がC#で何を表すのかを誰かが知っていますか?

string str = $"text";

Visual Studio 2015 CTPを使用しています。

回答:


418

$は省略形で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}";

あまり知られていない代替の方法もあります$@ (2つの記号の順序が重要です)。文字列全体を必要とせずに、@""文字列の機能を混合し$""て文字列補間をサポートでき\\ます。したがって、次の2行です。

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

出力されます:

c:\a\b\c

29
これは実際にはString.Formatを使用しているのではなく、コンパイラーベースの機能であり、実行時の機能ではないことに注意してください。
Shahar Prish 2017年

2
今日私が学んだことに注意してください。もしを使用すると$@、を使用して"キャラクターをエスケープする必要があります""。これは、だけを使用する場合には当てはまりません$
2017年

3
@Flater $記号とは関係ありません。これは、$記号が存在する前の動作と同じです。
BVernon 2018年

2
逐語的(@)と補間($)のシンボルの順序の重要性については、C#8で修正されているため、順序は問題になりません。参照:devsanon.com/uncategorized/...
elkaz

38

補間された文字列を作成します

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


10

クールな機能。一部の人に明らかでない場合、これがstring.formatよりも優れている理由を強調したいだけです。

パラメータを照合するために、string.formatを「{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}"は "0"を返すため、$ "{0}"を実行してstring.formatに渡すことはできません。

余談ですが、別の複製されたtpoicでコメントを読みました。コメントできなかったので、こちらです。彼は言った

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

複数の文字列オブジェクトを作成します。これは実際には当てはまりません。これを1行で行うと、1つの文字列のみが作成され、文字列キャッシュに配置されます。

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

これらはすべて文字列を返し、キャッシュに1つの値のみを作成します。

一方:

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

「;」が4つあるため、キャッシュに4つの異なる値を作成します。

したがって、次のようなコードを書く方が簡単ですが、CarlosMuñozが修正したように、5つの補間された文字列を作成します。

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

これにより、コードを非常に読みやすくしながら、キャッシュに単一の文字列が作成されます。パフォーマンスについてはわかりませんが、MSがまだ最適化していない場合は最適化するでしょう。


1
最後の例は間違っています。実際には、2つの文字列をクレートしています。1つは補間された文字列から、もう1つは残りの文字列からです。{myName}を持つものだけが補間され、その他は期待どおりに機能しないことに注意してください。
カルロスムニョス

1
また、5つの文字列の前に$を付加すると、それぞれに独自の5つの補間された文字列が作成さString.Format()れ、実行時にと連結されますString.Concat。だから、あなたが複数の行に分割していない方が良いです
カルロス・ムニョス

1
あなたは正しい@CarlosMuñoz、私はそれを修正しました。間違いを見つけてくれてありがとう。
BoBoDev 2018年

8

2つを組み合わせることもできます(かなり奇妙に見えますが)。

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

5
ちょうどあなたが入力したした順序を決めることができれば$@かを@$。残念ながら、それはただ$@
Bauss

2
@Baussこれは理にかなっています。@文字列リテラルの表現方法を定義します。$のショートカットですstring.Format。考えてみてください$(@"");
marsze

実際にはのショートカットではありませんstring.Format。これは、に解析される値を提示するのに甘くstring.Format、そのため部分的には意味がありますが、完全には意味がありません。
Bauss

3
$は基本的に暗黙の関数呼び出しであるのに対し、10進数リテラルの@場合と同様に、リテラルの一部ですm。そのため、論理的な順序は1つしかありません。
-marsze

2
これは主にここで示しただけです$が、互換性を最大化し、ディレクトリセパレータが「/」または「\」のどちらであるかをハードコーディングしないため、また、避けられないねじ込みが原因でダブルスラッシュまたはスラッシュが欠落することを避ける必要があります。Path.Combine()ディレクトリとファイルを操作するときは、文字列連結の代わりに使用することをお勧めします。
jrh 2018年

6

string.Formatよりも便利で、ここでもインテリセンスを使用できます。

ここに画像の説明を入力してください

そして、これが私のテスト方法です:

[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

$構文はいいですが、欠点が1つあります。

文字列テンプレートのようなものが必要な場合は、クラスレベルでフィールドとして宣言します。

次に、同じレベルで変数を宣言する必要があります...これは本当にクールではありません。

このようなことには、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;
 }
}

この答えは重要です。補間は$ stringを "呼び出す"ときに発生し、宣言するときに発生しないことを示しています。
dx_over_dt

1
クラススコープで補間変数を宣言するアンチパターンについてはあなたは正しいですが、それらの変数がすでにクラスのプロパティとして属している場合、このパターンはうまく機能します。
dx_over_dt

@dx_over_dtあなたは間違っています。補間された文字列は、宣言時に評価されます。これが、サンプルコードが意味をなさない理由です。また、コンパイルされません。
NineBerry、

@NineBerryあなたは正しいです。補間された文字列が宣言されたときに評価されることと、Example_ $ Formatがコンパイルされないことと、サンプルコードが意味をなさないことの両方について正しいです。
トム・


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.