C# 8.0 添加和增強的功能【基礎篇】

.NET Core 3.x.NET Standard 2.1支持C# 8.0 。
一、Readonly 成員可將 readonly 修飾符應用于結構的成員 , 來限制成員為不可修改狀態 。這比在C# 7.2中將 readonly 修飾符僅可應用于 struct 聲明更精細 。
public struct Point{public double X { get; set; }public double Y { get; set; }public double Distance => Math.Sqrt(X * X + Y * Y);public override string ToString() =>$"({X}, {Y}) is {Distance} from the origin";}與大多數結構一樣,ToString() 方法不會修改狀態 ??梢酝ㄟ^將 readonly 修飾符添加到 ToString() 的聲明來對此進行限制:
public readonly override string ToString() =>// 編譯器警告,因為 ToString 訪問未標記為 readonly 的 Distance 屬性$"({X}, {Y}) is {Distance} from the origin";// Distance 屬性不會更改狀態 , 因此可以通過將 readonly 修飾符添加到聲明來修復此警告public readonly double Distance => Math.Sqrt(X * X + Y * Y);注意:readonly 修飾符對于只讀屬性是必需的 。
編譯器會假設 get 訪問器可以修改狀態;必須顯式聲明 readonly 。
自動實現的屬性是一個例外;編譯器會將所有自動實現的 Getter 視為 readonly , 因此,此處無需向 X 和 Y 屬性添加 readonly 修飾符 。
通過此功能 , 可以指定設計意圖,使編譯器可以強制執行該意圖,并基于該意圖進行優化 。
二、默認接口方法從 .NET Core 3.0 上的 C# 8.0 開始,可以在聲明接口成員時定義實現 。最常見的方案是,可以將成員添加到已經由無數客戶端發布并使用的接口 。示例:
// 先聲明兩個接口// 客戶接口public interface ICustomer{IEnumerable<IOrder> PreviousOrders { get; }DateTime DateJoined { get; }DateTime? LastOrder { get; }string Name { get; }IDictionary<DateTime, string> Reminders { get; }// 在客戶接口中加入新的方法實現public decimal ComputeLoyaltyDiscount(){DateTime TwoYearsAgo = DateTime.Now.AddYears(-2);if ((DateJoined < TwoYearsAgo) && (PreviousOrders.Count() > 10)){return 0.10m;}return 0;}}// 訂單接口public interface IOrder{DateTime Purchased { get; }decimal Cost { get; }}// 測試代碼// SampleCustomer:接口 ICustomer 的實現,可不實現方法 ComputeLoyaltyDiscount// SampleOrder:接口 IOrder 的實現SampleCustomer c = new SampleCustomer("customer one", new DateTime(2010, 5, 31)){Reminders ={{ new DateTime(2010, 08, 12), "childs's birthday" },{ new DateTime(1012, 11, 15), "anniversary" }}};SampleOrder o = new SampleOrder(new DateTime(2012, 6, 1), 5m);c.AddOrder(o);//添加訂單o = new SampleOrder(new DateTime(2103, 7, 4), 25m);c.AddOrder(o);// 驗證新增的接口方法ICustomer theCustomer = c; // 從 SampleCustomer 到 ICustomer 的強制轉換Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}");// 若要調用在接口中聲明和實現的任何方法 , 該變量的類型必須是接口類型,即:theCustomer三、模式匹配的增強功能C# 8.0擴展了C# 7.0中的詞匯表(is、switch),這樣就可以在代碼中的更多位置使用更多模式表達式 。
3.1 switch 表達式區別與 switch 語句:
??變量位于 switch 關鍵字之前;
??將 case 和 : 元素替換為 =>,更簡潔、直觀;
??將 default 事例替換為 _ 棄元;
??實際語句是表達式,比語句更加簡潔 。
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)),};3.2 屬性模式借助屬性模式,可以匹配所檢查的對象的屬性 。
如下電子商務網站的示例 , 該網站必須根據買家地址(Address 對象的 State 屬性)計算銷售稅 。
// Address:地址對象;salePrice:售價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};

推薦閱讀