C# 7.0 添加和增強的功能【基礎篇】( 三 )

GetText 的方法是私有的:
private static string GetText(string path, string filename){var reader = File.OpenText($"{AppendPathSeparator(path)}{filename}");var text = reader.ReadToEnd();return text;string AppendPathSeparator(string filepath){return filepath.EndsWith(@"\") ? filepath : filepath + @"\";}}本地函數的一個實用功能是可以允許立即顯示異常 。
對于方法迭代器,僅在枚舉返回的序列時才顯示異常,而非在檢索迭代器時 。
對于異步方法 , 在等待返回的任務時,將觀察到異步方法中引發的任何異常 。
本地函數和lambda表達式是十分相似的,但兩者中選用一種的時機和條件其實是存在差別 。
// 本地函數public static int LocalFunctionFactorial(int n){return nthFactorial(n);int nthFactorial(int number) => number < 2? 1: number * nthFactorial(number - 1);}// Lambda 表達式public static int LambdaFactorial(int n){Func<int, int> nthFactorial = default(Func<int, int>);nthFactorial = number => number < 2? 1: number * nthFactorial(number - 1);return nthFactorial(n);}本地函數的命名方式與方法相同 。Lambda表達式是一種匿名方法,需要分配給 delegate 類型的變量,通常是 Action 或 Func 類型 。聲明本地函數時,此過程類似于編寫普通方法;聲明一個返回類型和一個函數簽名 。
Lambda表達式在聲明時轉換為委托 。本地函數更加靈活,可以像傳統方法一樣編寫,也可以作為委托編寫 。只有在用作委托時,本地函數才轉換為委托 。如果聲明了本地函數 , 但只是通過像調用方法一樣調用該函數來引用該函數,它將不會轉換成委托 。
本地函數可以避免Lambda表達式始終需要的堆分配 。如果本地函數永遠不會轉換為委托,并且本地函數捕獲的變量都不會被其他轉換為委托的Lambda或本地函數捕獲 , 則編譯器可以避免堆分配 。
yield 關鍵字的用法:
// 可將本地函數作為迭代器實現,使用 yield return 語法生成一系列值public IEnumerable<string> SequenceToLowercase(IEnumerable<string> input){if (!input.Any())throw new ArgumentException("There are no items to convert to lowercase.");return LowercaseIterator();IEnumerable<string> LowercaseIterator(){foreach (var output in input.Select(item => item.ToLower()))yield return output;}}雖然本地函數對 lambda 表達式可能有點冗余,但實際上它們的目的和用法都不一樣 。如果想要編寫僅從上下文或其他方法中調用的函數,則使用本地函數更高效 。
七、擴展 Expression bodied 成員在C# 6.0中已經新增了表達式主體定義,而在當前版本中進行了擴展 。擴展的內容包括下面幾點 。
可以使用表達式主體定義來實現屬性 get 和 set 訪問器 。
public class Location{private string locationName;public Location(string name) => Name = name;public string Name{get => locationName;set => locationName = value;}}構造函數的表達式主體定義通常包含單個賦值表達式或一個方法調用 , 該方法調用可處理構造函數的參數,也可初始化實例狀態 。
// 其構造函數具有一個名為“name”的字符串參數,表達式主體定義向 Name 屬性分配參數public class Location{private string locationName;public Location(string name) => Name = name;public string Name{get => locationName;set => locationName = value;}}終結器的表達式主體定義通常包含清理語句,例如釋放非托管資源的語句 。
// 定義一個終結器,該終結器使用表達式主體定義來指示已調用該終結器public class Destroyer{public override string ToString() => GetType().Name;~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");}索引器與使用屬性一樣,如果 get 訪問器包含返回值的單個表達式或 set 訪問器執行簡單的賦值 , 則索引器 get 和 set 訪問器包含表達式主體定義 。
using System;using System.Collections.Generic;// 其中包含一個內部 String 數組,該數組包含大量體育運動的名稱// 索引器的 get 和 set 訪問器都以表達式主體定義的形式實現public class Sports{private string[] types = { "Baseball", "Basketball", "Football","Hockey", "Soccer", "Tennis","Volleyball" };public string this[int i]{get => types[i];set => types[i] = value;}}八、ref 局部變量在變量類型之前添加 ref

推薦閱讀