只读成员
private struct Point
{
public Point(double x, double y)
{
X = x;
Y = y;
}
private double X { get; set; }
private double Y { get; set; }
private readonly double Distance => Math.Sqrt(X * X + Y * Y);
public override readonly string ToString() =>
$"({X}, {Y}) is {Distance} from the origin";
}
使用readonly修饰tostring方法,表示它不可修改
默认接口方法
/// <summary>
/// 默认接口方法
/// </summary>
private interface IWork
{
public void Work()
{
Console.WriteLine("Work");
}
}
现在可以在接口中定义默认的方法,而不是只能申明void Work();
更多的模式匹配
使用switch表达式的模式匹配
public enum Rainbow
{
Red,
Orange,
Yellow,
Green,
Blue,
Indigo,
Violet
}
//switch表达式
public static Color FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => Color.Red,
Rainbow.Orange => Color.Orange,
Rainbow.Yellow => Color.Yellow,
Rainbow.Green => Color.Green,
Rainbow.Blue => Color.Blue,
Rainbow.Indigo => Color.Indigo,
Rainbow.Violet => Color.Violet,
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
在变量后面使用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 struct Address
{
public string State { get; set; }
}
对location变量的State属性进行模式匹配
元组模式
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"
};
位置模式
//位置模式,使用解构将属性解构的离散变量,如果可以访问 Deconstruct 方法,就可以使用位置模式 检查对象的属性并将这些属性用于模式
public class XPoint
{
public int X { get; set; }
public int Y { get; set; }
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}
public int GetNumber(XPoint point) => point switch
{
(0, 0) => 0,
var (x, y) when x > 0 && y > 0 => 1,
var (x, y) when x < 0 && y > 0 => 2,
var (x, y) when x < 0 && y < 0 => 3,
var (x, y) when x > 0 && y < 0 => 4,
var (_, _) => -1,
_ => -2
};
using申明
/// <summary>
/// using 声明,using 表达式的操作数可以实现 IDisposable 或 IAsyncDisposable
/// </summary>
public void UsingStatement()
{
using var file = new System.IO.StreamWriter("WriteLines2.txt");
}
可以对异步可释放类型使用using关键字进行vb.net教程c#教程释放
静态本地函数
/// <summary>
/// 静态本地函数,在本地函数中使用static关键字
/// </summary>
private class StaticLocalFunction
{
int N()
{
int y;
LocalFunction();
return y;
void LocalFunction() => y = 0;
}
int M()
{
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}
}
可以在本地函数申明中使用static关键字
索引和范围
private class IndexRange
{
string[] 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
void Test()
{
//>=index_1 && < index_4
var quickBrownFox = words[1..4];
var lazyDog = words[^2..^0];
}
}
null合并赋值
/// <summary>
/// null合并赋值
/// </summary>
private void NullMergeAssignment()
{
List<int> list = new List<int>();
List<int> numbers = list.Where(x => x > 20).ToList();
numbers ??= new List<int>();
}
当左操作数计算为 null 时,将??= 右操作数的值分配给左操作数
异步流
public static class AsyncStream
{
public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{
for (int i = 0; i < 20; i++)
{
await Task.Delay(100);
yield return i;
}
}
public static async void GetNumbers()
{
var c = CSharp8.AsyncStream.GenerateSequence();
await foreach (var number in c)
{
Console.WriteLine(number);
}
}
}
GetNumbers使用await等待返回结果,每隔100ms会输出i++的值