什么是$ -operator应该对字符串意味着什么?

时间:2016-01-01 18:10:04

标签: c# string

所以,我刚刚与the comments section中的用户进行了以下对话。

我:

Year year = new Year{ State = States.Happy };

他们:

eventStream.ReceiveJoke += joke =>  
    Console.WriteLine($"Pretty nice joke: {joke}, Thanks!!!");

而且,就像我一样,我不知道他对美元符号的意思,但我觉得问他是太尴尬了。

4 个答案:

答案 0 :(得分:36)

这是一个内插的字符串文字,在C#6中引入。

它大致相当于:

eventStream.ReceiveJoke += joke =>  
    Console.WriteLine(string.Format("Pretty nice joke: {0}, Thanks!!!", joke));

编译器在$引入的任何字符串文字中查找大括号,并对其应用字符串格式。您可以使用(大多数)任意表达式,而不仅仅是变量,例如

Console.WriteLine($"{year.State} {2000 + 16}"); // Happy 2016

答案 1 :(得分:24)

这是允许你创建插值字符串的符号,它是C#6的新功能,我喜欢它。

它也是一个Syntax Sugar,我将在最后解释它的含义。

让我们看看行动。看下面的代码

public string Receive(int value)
{
    return String.Format("Received: {0}", value);
}

public string Receive6(int value)
{
    return $"Received: {value}";
}

编译后会发生什么

他们将具有相同的IL实现,从接收

看这里的IL(在调试模式下,未优化)
.method public hidebysig instance string Receive (int32 'value') cil managed 
{
    // Method begins at RVA 0x22d4
    // Code size 22 (0x16)
    .maxstack 2
    .locals init (
        [0] string
    )

    IL_0000: nop
    IL_0001: ldstr "Received: {0}"
    IL_0006: ldarg.1
    IL_0007: box [mscorlib]System.Int32
    IL_000c: call string [mscorlib]System.String::Format(string, object)
    IL_0011: stloc.0
    IL_0012: br.s IL_0014

    IL_0014: ldloc.0
    IL_0015: ret
} // end of method Program::Receive

现在让我们看一下来自 Receive6

的IL(在调试模式下,未优化)
.method public hidebysig instance string Receive6 (int32 'value') cil managed 
{
    // Method begins at RVA 0x22f8
    // Code size 22 (0x16)
    .maxstack 2
    .locals init (
        [0] string
    )

    IL_0000: nop
    IL_0001: ldstr "Received: {0}"
    IL_0006: ldarg.1
    IL_0007: box [mscorlib]System.Int32
    IL_000c: call string [mscorlib]System.String::Format(string, object)
    IL_0011: stloc.0
    IL_0012: br.s IL_0014

    IL_0014: ldloc.0
    IL_0015: ret
} // end of method Program::Receive6

正如你亲眼所见,IL几乎是一样的。

现在让我们了解什么是Syntax Suggar

  

在计算机科学中,语法糖是编程语言中的语法,旨在使事物更易于阅读或表达。它使语言“更甜”供人类使用:事物可以更清晰,更简洁地表达,或者以某些人可能更喜欢的替代方式表达。

来自https://en.wikipedia.org/wiki/Syntactic_sugar

因此,要编写大量string.Format,使用字符串插值,编译器将为您工作,并使用string.Format在另一个代码中转换您编写的语法。 p>

我可以使用string.Format中的格式化选项吗?

是的,你可以,看下面

public static string Receive(int value) 
    => string.Format("Received: {0, 15:C}", value);

public static string Receive6(int value) 
    => $"Received: {value,15:C}";

Console.WriteLine(Receive(1));
Console.WriteLine(Receive6(1));
Console.WriteLine($"Current data: {DateTime.Now: MM/dd/yyyy}")

输出(我的文化是pt-br)

Received:         R$ 1,00
Received:         R$ 1,00
Current data:  01/01/2016

Obs。:我想提一下,没有性能差异,因为使用字符串插值e string.Format是完全一样的事情

答案 2 :(得分:8)

简而言之,这是提高代码可读性并缩短代码长度的好方法。它比String.Concat或+运算符要好得多,因为字符串插值只执行String.Format一次(实际上它编译为String.Format方法调用)并且您只需阅读表达从左到右。

  

String.Format它的表兄弟非常多才多艺而且很有用,但是它们的使用有点笨重而且容易出错。特别不幸的是在格式字符串中使用{0}等占位符,它必须与单独提供的参数对齐:

var s = String.Format("{0} is {1} year{{s}} old", p.Name, p.Age);
     

字符串插值允许您通过在字符串文字中直接使用“孔”将表达式放在适当的位置:

var s = $"{p.Name} is {p.Age} year{{s}} old";
     

String.Format一样,可以给出可选的对齐和格式说明符:

var s = $"{p.Name,20} is {p.Age:D3} year{{s}} old";
     

孔的内容几乎可以是任何表达式,包括其他字符串:

var s = $"{p.Name} is {p.Age} year{(p.Age == 1 ? "" : "s")} old";
     

请注意,条件表达式是括号的,因此:" s"不会与格式说明符混淆。

Via

答案 3 :(得分:5)

这是C#6的一个新功能,称为字符串插值,

  

可让您更轻松地格式化字符串。 String.Format及其堂兄是   非常通用,但它们的使用有点笨重且容易出错。

有关此问题的详细信息,请查看here

示例

让我们有以下课程:

public class Customer
{
    public int Id { get; set; }
    public string FirstName {get; set;}
    public string LastName { get; set; }
}

让我们假设我们想要使用ToString方法,如下所示:

public override string ToString()
{
    return string.Format("The customer with Id: {0} has as FirstName: {1} and as LastName: {2}", Id, FirstName,
            LastName);
}

在C#6中,我们可以使用字符串插值获得相同的结果。

public override string ToString()
{
    return $"The customer with Id: {Id} has as FirstName: {FirstName} and as LastName: {LastName}";
}

字符串插值的好处:

  • 字符串比复合字符串更容易阅读。
  • 格式字符串后面的参数导致语法错误减少,这些参数的顺序不正确,或完全丢失并导致异常。