【问题标题】:What's $-operator supposed to mean for a string?$-operator 应该对字符串意味着什么?
【发布时间】:2016-04-06 03:33:30
【问题描述】:

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

我:

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

他们:

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

而且,像我这样的书呆子,我想知道他所说的美元符号是什么意思,但我觉得问他太尴尬了。

【问题讨论】:

  • 康拉德,问我这个没问题,我喜欢帮助别人:D
  • @AlbertoMonteiro 你不应该看到这个。我想用更诙谐的评论回复你。该死... year.State = States.Darn;
  • 我看到并已经回答了这个问题:P
  • 我不想编辑以防我错过了你的推理,但我建议问它是什么意思,而不是它应该是什么意思:-)
  • @SteveJessop 好建议。但是,我不想进行更改,因为现在 Skeety 显示为合著者,对我们来说,低指针,它就像一个徽章(青铜,银,金,飞碟),呵呵。显然,如果您编辑,我不会回滚。也许你可以让乔恩编辑? (开个玩笑,开个玩笑。)

标签: c# string


【解决方案1】:

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

大致相当于:

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

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

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

【讨论】:

  • 为什么叫插值?
  • 乔恩,我的印象是字符串插值产生的 IL 与等价的 string.Format 相同。这是假的吗?
  • @Gusdor:这取决于你用它做什么。例如,有时您将其用作FormattableString,以便稍后对其进行格式化或在不变的文化中这样做。这就是为什么我把它“广泛”等同起来,以避免过度概括:)
  • @FᴀʀʜᴀɴAɴᴀᴍ 什么是YAB
  • @KonradViltersten:我怀疑在这种情况下这是“又一个徽章”。
【解决方案2】:

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

它也是一个语法糖,我会在最后解释它的含义。

让我们看看实际情况。看下面的代码

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

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

编译后会发生什么

它们将具有相同的 IL 实现,请看这里来自 Receive

的 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 几乎相同。

现在让我们了解一下什么是语法糖

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

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

因此,如果要编写大量 string.Format,请使用字符串插值,编译器将为您工作并转换您编写的语法,在另一个代码中,在这种情况下,使用 string.Format

我可以使用像 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 是完全一样的

【讨论】:

    【解决方案3】:

    简而言之,这是提高代码可读性和减少代码长度的好方法。它比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

    【讨论】:

    • 请在引用另一篇文章时使用块引用来明确说明,而不仅仅是文章末尾的链接,这并不能说明您只是在引用 MSDN。
    • 您为什么更改我的编辑以使答案中的代码只是从 Roslyn github 页面引用?它更简单,IMO。
    • 对不起,只是并发冲突。另外,你对我的第一段也做了同样的事情。
    • 这是什么{{s}} 东西?
    • @Random832 因为在字符串插值中 { 是一个特殊字符,如果你想写一个 { 而不是用它作为特殊字符,你必须将它转义,转义方法是添加另一个 {,这也发生在 string.Format 中。
    【解决方案4】:

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

    字符串插值的好处:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-22
      • 2019-12-03
      • 2011-12-28
      • 2020-10-12
      • 2011-06-11
      • 2010-10-02
      相关资源
      最近更新 更多