UTF-8 字符串(UTF-8 String Literals)
u8
后缀,以便立即将它们转换为 UTF-8:
var u8 = "This is a UTF-8 string!"u8;
ReadOnlySpan<byte>
形式。对于那些需要 UTF-8 编码的场景,这可能比一些专门的新的 UTF-8 字符串类型更有用。- 以至少三个双引号字符序列 (
"""
) 开头和结尾。可以使用三个以上的连续字符开始和结束序列,以支持包含三个(或更多)重复引号字符的字符串字面量。 - 单行原始字符串字面量需要左引号和右引号字符位于同一行上。
- 多行原始字符串字面量需要左引号和右引号字符位于各自的行上。
- 在多行原始字符串字面量中,会删除右引号左侧的任何空格。
var raw1 = """This\is\all "content"!""";
Console.WriteLine(raw1);
This prints:
This\is\all "content"!
"
s 成为你内容的一部分,只需在外部使用更多的"
s。开头和结尾必须一致。var raw2 = """""I can do ", "", """ or even """" double quotes!""""";
这使得粘贴、维护和一目了然地阅读文字所包含的内容变得非常容易。
多行 raw string literals 也可以截断前导空格:末端引号的位置决定了空格开始包含在输出中的位置:
var raw3 = """
<element attr="content">
<body>
This line is indented by 4 spaces.
</body>
</element>
""";
// ^white space left of here is removed
由于末端引号的左侧有四个空格,因此将从每行内容的开头删除四个空格,从而产生以下输出:
<elementattr="content">
<body>
This line is indented by 4 spaces.
</body>
</element>
此外,Raw string literals 还支持插值,可在文档中阅读有关的更多信息:https://learn.microsoft.com/dotnet/csharp/programming-guide/strings/#raw-string-literals
对静态成员进行抽象
在 C# 11 中发布了对接口中静态虚拟成员的支持,此功能在 C# 10 中处于预览状态。有了它,你现在可以定义一个非常简单的数学接口:
publicinterfaceIMonoid<TSelf> whereTSelf: IMonoid<TSelf>
{
publicstaticabstractTSelfoperator+(TSelf a, TSelf b);
publicstaticabstractTSelfZero{ get; }
}
TSelf
类型参数传递来实现此接口:publicstructMyInt: IMonoid<MyInt>
{
intvalue;
publicMyInt(int i) => value= i;
publicstaticMyIntoperator+(MyInt a, MyInt b) => newMyInt(a.value+ b.value);
publicstaticMyIntZero=> newMyInt(0);
}
T AddAll<T>(params T[] elements) where T : IMonoid<T>
{
T result = T.Zero;
foreach(var element in elements)
{
result += element;
}
return result;
}
T
受IMonoid<T>
接口约束,这使得该接口的静态虚拟成员Zero
和+
可以在T
itself 上被调用。MyInt
来调用泛型方法,而+
和Zero
的正确实现则通过类型参数传递进来:MyInt sum = AddAll<MyInt>(newMyInt(3), newMyInt(4), newMyInt(5));
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
Console.WriteLine(numbers is [1, 2, 3, 4]); // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // True
如前面的示例所示,当每个嵌套模式与输入序列的相应元素匹配时,列表模式就会匹配。可使用列表模式中的任何模式。若要匹配任何元素,请使用弃元模式,或者,如果还想捕获元素,请使用 var 模式,如以下示例所示:
List<int> numbers = new() { 1, 2, 3 };
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.
..
,如以下示例所示:Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]); // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]); // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]); // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]); // False
Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]); // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]); // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]); // True
Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]); // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]); // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]); // False
voidMatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.
voidValidate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}
Validate(new[] { -1, 0, 1 }); // output: not valid
Validate(new[] { -1, 0, 0, 1 }); // output: valid
更多详情可查看相关文档:https://learn.microsoft.com/dotnet/csharp/language-reference/operators/patterns#list-patterns
Required members
开发团队已经在多个版本中进行了改进对象的创建和初始化的工作,C# 11 则通过 required members 来继续这些改进。
required
。这意味着,当创建该类型的对象时,它必须被对象初始化器初始化:publicclassPerson
{
public required stringFirstName{ get; init; }
publicstring? MiddleName{ get; init; }
public required stringLastName{ get; init; }
}
Person
是错误的:var person = newPerson{ FirstName= "Ada"}; // Error: no LastName!
相关博文
C# 11正式发布