c# 7.0 新特性

系列文章


內聯申明out變量

在7.0以前我們遇到使用帶有out參數的方法時需要單獨申明這個變量,在7.0以後可以內聯的使用out變量

<code>Int32 result;
Int32.TryParse(input, out result); // use out variable in c#6.0


Int32.TryParse(input, out Int32 result); // use out variable in c#7.0+
Int32.TryParse(input, out var result); // use implicitly out variable in c#7.0+/<code>

元組

C# 為用於說明設計意圖的類和結構提供了豐富的語法。但是有時候這種語法很笨重;在7.0以前c#也提供元組,當不是語言級別的支持

元組是包含多個字段以表示數據成員的輕量級數據結構。 這些字段沒有經過驗證,並且你無法定義自己的方法

<code>(string Alpha, string Beta) namedLetters = ("a", "b");   // use Tuples in c#7.0+
Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}"); /<code>

棄元

在使用具有out參數的方法調用時,或者元組析構時,有時候必須為了不需要使用的參數或者元素定義一個變量,在c#7.0可以通過使用名為 _(下劃線) 的符號來放棄指定位置的值;

棄元可以使用在1)元素或用戶自定義類型解構,2)調用具有out參數的方法,3)is或者swith的模式匹配語句中,4)賦值語句的左值

<code>在對元組或用戶定義的類型進行解構時。
在使用 out 參數調用方法時。
在使用 is 和 switch 語句匹配操作的模式中。
在要將某賦值的值顯式標識為棄元時用作獨立標識符。/<code>

模式匹配

模式匹配支持 is 表達式和 switch 表達式。

<code>// is 增強的模式匹配
if (input is int count) // 經過測試後將值賦給後面類型正確的新變量
sum += count;

// switch 模式匹配
public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
int sum = 0;
foreach (var i in sequence)
{
switch (i)
{
case 0: // 是常見的常量模式。
break;
case IEnumerable childSequence: //一種類型模式
{
foreach(var item in childSequence)

sum += (item > 0) ? item : 0;
break;
}
case int n when n > 0: // 具有附加 when 條件的類型模式
sum += n;
break;
case null: // null 模式
throw new NullReferenceException("Null found in sequence");
default: // 常見的默認事例
throw new InvalidOperationException("Unrecognized type");
}
}
return sum;
}
/<object>/<code>

ref 局部變量和返回結果

允許返回和使用在其它地方定義的引用變量

<code>// Demo 在一個矩陣中查找指定元素並返回其引用
public static ref int Find(int[,] matrix, Func predicate)
{
for (int i = 0; i < matrix.GetLength(0); i++)
for (int j = 0; j < matrix.GetLength(1); j++)
if (predicate(matrix[i, j]))
return ref matrix[i, j];
throw new InvalidOperationException("Not found");
}
/<code>

本地函數

許多類的設計都包括僅從一個位置調用的方法。 這些額外的私有方法使每個方法保持小且集中。

<code>// Demo 通過本地函數使得方法中參數檢驗肯執行分離
public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
if (start < 'a' || start > 'z')
throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
if (end < 'a' || end > 'z')
throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

if (end <= start)
throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

return alphabetSubsetImplementation();

IEnumerable<char> alphabetSubsetImplementation()
{
for (var c = start; c < end; c++)
yield return c;
}
}/<char>/<char>/<code>

expression-bodied 成員

在c# 6.0中只為只讀屬性和成員函數引入了表達式體,在c# 7.0 擴展到可在屬性,索引器,終結器,get,set訪問器使用

<code>// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

private string label;

// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value ?? "Default label";
}/<code>

throw 表達式

在c# 7.0以前 throw 不可以在三元表達式 ?? 表達式 以及表達式體中出現,下面演示在三元表達式中使用throw表達式

<code>// use throw expression in condational opeartor, you must appear in an if/else statement.1
string arg = args.Length >= 1 ? args[0] : throw new ArgumentException("You must supply an argument");/<code>

通用的異步返回類型

從異步方法返回 Task 對象可能在某些路徑中導致性能瓶頸。 Task 是引用類型,因此使用它意味著分配對象。 如果使用 async 修飾符聲明的方法返回緩存結果或以同步方式完成,那麼額外的分配在代碼的性能關鍵部分可能要耗費相當長的時間。 如果這些分配發生在緊湊循環中,則成本會變高。

新的特性去除了異步方法必須從Task,Task, void 返回,只要返回值具有可以訪問的GetAwaiter方法即可,官方實例

<code>public async ValueTask Func()
{
await Task.Delay(100);
return 5;
}
/<code>

數字文本語法改進

直接上代碼演示,看效果

<code>public const int Sixteen =   0b0001_0000;
public const int ThirtyTwo = 0b0010_0000;
public const int OneMillion = 100_0000;
public const int ThreeBillion = 3_0000_0000;
public const double AvogadroConstant = 6.012_140_857_747_474e23;/<code>

通過在數字中添加下劃線來增加可讀性


分享到:


相關文章: