我本来想使用原样字符串,但我误打了$
而不是@
。
但编译器没有报错,成功编译通过。
我想知道它是什么以及它的作用。我搜索了一下,但是没有找到任何相关信息。
然而,它与原样字符串不同,因为我不能这样写:
string str = $"text\";
在C#中,字符串前面的$
字符代表什么意思?
string str = $"text";
我正在使用 Visual Studio 2015 CTP。
$
是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
它创建了一个插值字符串。
来自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(...,[在此处插入区域设置])}
。 - jrh示例代码
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
包含 "Hello, World"。
Console.WriteLine(message); // Prints Hello, World
参考资料 - MSDN
请注意,您还可以组合这两者,这非常酷(虽然看起来有点奇怪):
// simple interpolated verbatim string
WriteLine($@"Path ""C:\Windows\{file}"" not found.");
@
定义了字符串字面量的表示方式。 $
是string.Format
的快捷方式。将其视为$(@"");
。 - marsze$
基本上是一个隐式的函数调用,而@
是字面量的一部分,就像十进制字面量中的m
一样。这就是为什么只有一个逻辑顺序。 - marsze$
,但为了最大兼容性,不硬编码目录分隔符是 '/' 还是 '',并且避免不可避免的错误导致双斜杠或缺少应有的斜杠,我建议在处理目录和文件时使用Path.Combine()
而不是使用字符串连接。 - jrhPath.Combine()
)。 - jrhstring 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个不同的值。
因此,编写以下代码将更加容易,但是您将创建五个插值字符串,就像Carlos Muñoz所更正的那样:
string msg = $"Hello this is {myName}, " +
$"My phone number {myPhone}, " +
$"My email {myEmail}, " +
$"My address {myAddress}, and " +
$"My preference {myPreference}.";
这将在缓存中创建一个单一的字符串,同时您可以编写非常易于阅读的代码。我不确定性能如何,但我确信如果尚未进行优化,微软将对其进行优化。
String.Format()
的插值字符串,并在运行时使用String.Concat
连接起来。因此最好不要将其拆分为多行。 - Carlos Muñozstring.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://learn.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.
$语法很好,但有一个缺点。
如果你需要像字符串模板这样的东西,它在类级别上作为字段声明...应该只有一个地方。
然后你必须在同一级别上声明变量...这不太好。
对于这种情况,使用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.Format("{0}{1}", secondParamIsMissing)
抛出异常。
这比使用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);
}
我不知道它是如何工作的,但你也可以使用它来制表你的值!
示例:
Console.WriteLine($"I can tab like {"this !", 5}.");
$@
,那么你必须通过使用""
来转义"
字符。但是当你只使用$
时,情况并非如此。 - Flater