C#8.0新特性的学习笔记

Readonly 成员

可将 readonly 修饰符应用于结构的成员。 它指示该成员不会修改状态。

switch 表达式

更新增加新语法,可以直接使用枚举类型或类的判断条件
了解即可,旧语法同样可以。只不过增加了对元组的支持。
一个枚举对象如下

public enum Rainbow
{
    Red,
    Orange,
    Yellow,
    Green,
    Blue,
    Indigo,
    Violet
}

常规的switch语句如下

public static RGBColor FromRainbowClassic(Rainbow colorBand)
{
    switch (colorBand)
    {
        case Rainbow.Red:
            return new RGBColor(0xFF, 0x00, 0x00);
        case Rainbow.Orange:
            return new RGBColor(0xFF, 0x7F, 0x00);
        case Rainbow.Yellow:
            return new RGBColor(0xFF, 0xFF, 0x00);
        case Rainbow.Green:
            return new RGBColor(0x00, 0xFF, 0x00);
        case Rainbow.Blue:
            return new RGBColor(0x00, 0x00, 0xFF);
        case Rainbow.Indigo:
            return new RGBColor(0x4B, 0x00, 0x82);
        case Rainbow.Violet:
            return new RGBColor(0x94, 0x00, 0xD3);
        default:
            throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand));
    };
}

而新增语法可以将switch语法优化

	public static RGBColor FromRainbow(Rainbow colorBand) =>
    colorBand switch
    {
        Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
        Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
        Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
        Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
        Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
        Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
        Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
        _              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
    };

注意几点

  • 变量位于 switch 关键字之前。 不同的顺序使得在视觉上可以很轻松地区分 switch 表达式和 switch 语句。
  • 将 case 和 : 元素替换为 =>。 它更简洁,更直观。
  • 将 default 事例替换为 _ 弃元。
  • 正文是表达式,不是语句。

对类的对象,可以使用如下用法

	public static decimal ComputeSalesTax(Address location, decimal salePrice) =>
    location switch
    {
        { State: "WA" } => salePrice * 0.06M,
        { State: "MN" } => salePrice * 0.075M,
        { State: "MI" } => salePrice * 0.05M,
        // other cases removed for brevity...
        _ => 0M
    };

也支持元组模式

	public static string RockPaperScissors(string first, string second)
    => (first, second) switch
    {
        ("rock", "paper") => "rock is covered by paper. Paper wins.",
        ("rock", "scissors") => "rock breaks scissors. Rock wins.",
        ("paper", "rock") => "paper covers rock. Paper wins.",
        ("paper", "scissors") => "paper is cut by scissors. Scissors wins.",
        ("scissors", "rock") => "scissors is broken by rock. Rock wins.",
        ("scissors", "paper") => "scissors cuts paper. Scissors wins.",
        (_, _) => "tie"
    };

using 声明

using可以不使用{}全部括起来,可以在函数作用范围结束后自动释放回收。

static int WriteLinesToFile(IEnumerable<string> lines)
{
    using var file = new System.IO.StreamWriter("WriteLines2.txt");
    // Notice how we declare skippedLines after the using statement.
    int skippedLines = 0;
    foreach (string line in lines)
    {
        if (!line.Contains("Second"))
        {
            file.WriteLine(line);
        }
        else
        {
            skippedLines++;
        }
    }
    // Notice how skippedLines is in scope here.
    return skippedLines;
    // file is disposed here
}//执行后 此处释放file 

相当于

static int WriteLinesToFile(IEnumerable<string> lines)
{
    // We must declare the variable outside of the using block
    // so that it is in scope to be returned.
    int skippedLines = 0;
    using (var file = new System.IO.StreamWriter("WriteLines2.txt"))
    {
        foreach (string line in lines)
        {
            if (!line.Contains("Second"))
            {
                file.WriteLine(line);
            }
            else
            {
                skippedLines++;
            }
        }
    } // file is disposed here
    return skippedLines;
}

异步流

C# 8.0 开始,可以创建并以异步方式使用流。 返回异步流的方法有三个属性:

  1. 它是用 async 修饰符声明的。
  2. 它将返回 IAsyncEnumerable。
  3. 该方法包含用于在异步流中返回连续元素的 yield return 语句。

官方文档举例如下,个人觉得如果使用异步还需要获取值,那么还不如直接await等待函数执行完,获取返回值。

public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{
    for (int i = 0; i < 20; i++)
    {
        await Task.Delay(100);
        yield return i;
    }
}
await foreach (var number in GenerateSequence())
{
    Console.WriteLine(number);
}

索引和范围

这个新特性不错,python中的数组遍历实在是方便。现在c#终于增加了特性。
官方说明如下
此语言支持依赖于两个新类型和两个新运算符:

  1. System.Index 表示一个序列索引。 来自末尾运算符 ^ 的索引,指定一个索引与序列末尾相关。
  2. System.Range 表示序列的子范围。 范围运算符 …,用于指定范围的开始和末尾,就像操作数一样。

首先一个数组

var words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0

获取最后一个元素旧语法为

words[words.length-1]

新版本

words[^1]

获取一定范围的数组,注意左闭右开,包括左边的,不包含右侧的,下方的意思是获取1-3的元素 “quick”、“brown”和“fox”

var quickBrownFox = words[1..4];

以下代码创建了一个包含单词“quick”、“brown”和“fox”的子范围。 它包括 words[1] 到 words[3]。 元素 words[4] 不在该范围内。

var lazyDog = words[^2..^0];

以下代码使用“lazy”和“dog”创建一个子范围。 它包括 words[^2] 和 words[^1]。 末尾索引 words[^0] 不包括在内:

var lazyDog = words[^2..^0];

下面的示例为开始和/或结束创建了开放范围:

var allWords = words[..]; // contains "The" through "dog".
var firstPhrase = words[..4]; // contains "The" through "fox"
var lastPhrase = words[6..]; // contains "the", "lazy" and "dog"

此外可以将范围声明为变量:

Range phrase = 1..4;
var text = words[phrase];

Null 合并赋值

**合并赋值运算符 **??=
仅当左操作数计算为 null 时,才能使用运算符 ??= 将其右操作数的值分配给左操作数。

//声明两个为空的对象
List<int> numbers = null;
int? i = null;
//numbers为null 右侧赋值给左侧
numbers ??= new List<int>();
//i为Null 赋值17
numbers.Add(i ??= 17);
//i不为null  不操作 保留原值
numbers.Add(i ??= 20);

Console.WriteLine(string.Join(" ", numbers));  // output: 17 17
Console.WriteLine(i);  // output: 17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值