TOC

This article is currently in the process of being translated into Chinese (~89% done).

Operators:

The String Interpolation Operator

本教程其它部分已经大篇幅讨论过字符串类型,因为处理文本在编程过程中是非常重要的。本章将重点介绍一个特殊的字符串处理运算符,该运算符在字符串变量定义时有不少讲究。这就是字符串插值运算符(在C# 6.0版本中引入),允许在字符串中插入特殊标记,之后编译器会用相关的值替换这些标记。其功能类似之前介绍过的String.Format()方法,但是其句法可读性更好,用起来更方便。

字符串插值的实现很简单 - 只要在字符串前面加上$字符即可。同样的,还是直接上例子:

string name = "John Doe";
int age = 42;

Console.WriteLine(name + " is " + age + " years old");
Console.WriteLine($"{name} is {age} years old");

最后两行代码的功能完全一样:前一行用的是传统的方式,在连接字符串时使用了前面定义的两个变量,后一行使用插值运算。注意使用花括号把变量直接插入到字符串里面的方法。虽然它们被包含在字符串内部,编译器仍然会检查出要插入的变量!

此外,可以插入的变量不限简单类型 - 也可以使用复杂变量的属性,跟使用常规的字符串连接方式时是一样的。如下例所示:

var user = new
{
    Name = "John Doe",
    Age = 42
};
Console.WriteLine($"{user.Name} is {user.Age} years old");

格式字符串

默认情况下,被包含的变量都会被通过调用其ToString()方法而转化为该变量的字符串形式。不过有时会想对变量的显示进行更多的控制,幸好,这很简单,使用格式字符串就好。只需在变量后面跟一个冒号(:),然后再加上所需的格式字符串,如下例所示:

double daysSinceMillenium = (DateTime.Now - new DateTime(2000, 1, 1)).TotalDays;  
Console.WriteLine($"Today is {DateTime.Now:d} and {daysSinceMillenium:N2} days have passed since the last millennium!");

输出结果大致如下,根据系统的日期和数字格式设置会有所不同:

Today is Friday, June 29, 2018 and 6,754.49 days have passed since the last millenium!

注意此处日期是如何以长日期格式(以“D”格式字符串表示)显示的,以及数字是如何完美地以千位分隔及两位小数的格式(以“N2”格式字符串表示)显示的。

如果还想进一步控制,可以把默认格式字符串改为定制格式字符串,比如,对于日期:

Console.WriteLine($"Today is {DateTime.Now:yyyy-MM-dd}");

可用于插入字符串的格式化DataTime类型的格式化字符串很多。要了解全部内容,请参考文档

超越变量

前面介绍了怎样在字符串中插入变量,甚至对象属性,以及格式化其输出有多简单。但是字符串插值运算已经超越了上述内容,因为可以在字符串中实际插入完整的表达式,只要表达式的结果是可以连接到字符串上的某个东西就好。最常见的例子是经典的“是否以s结尾”的问题 - 比如,当需要一个即可能是“1岁”也可能是“2岁s(英语years为year的复数)”的字符串时(说明:英语的复数通常需要在该单词后面加s。因此本例对汉语读者可能不合适)。可以用字符串插值运算直接实现此功能,只需简单地在字符串中使用三元运算符:

string name = "John Doe";
int age = 42;

Console.WriteLine($"{name} is {age} year{(age == 1 ? "" : "s")} old");

注意此处用一对括号括起来的一个字符串完成了原本需要用if-then-else语句才能完成的功能。之所以可以这样做是因为该表达式返回了一个字符串 - 空串或是“s”。也可以使用数学运算:

Console.WriteLine($"5 + 5 * 2 = {((5 + 5) * 2)}");

这依然可以,因为其返回结果是可以被转化(通过调用其ToString()方法)为字符串的。

字符串插值与转义

使用字符串插值很快就会面临一个问题:怎么在字符串中包含特殊字符,比如,花括号,而不被编译器解释为插值运算?这类问题通常会用转义来解决 - 通过在需要转义的字符前面/或后面加上另一个字符 ,来屏蔽该字符的操作(而把其当作字符本身看待)。插值运算也是这样处理的,如果要把花括号当作花括号本身来处理,就需要使用两层花括号,如下所示:

Console.WriteLine($"Insert {name} between curly braces: {{name here}}");

结果为:

Insert John Doe between curly braces: {name here}

总结

传统的字符串连接方式的笨拙突显了字符串插值运算的优点!此运算符在C# 6.0中引用,允许以非常自然易懂的方式把变量包含在文本里面。同时该操作符还允许把表达式集成到字符串里面,不过要注意 - 从某个角度来看,被插值的字符串可能会变得过于复杂,因而变得难以理解,还不如使用传统的方法。


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!