欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#12中的新增功能使用總結(jié)

 更新時間:2023年10月08日 11:30:13   作者:百寶門園地  
這篇文章主要為大家詳細介紹了C#12中的7個新增功能的使用,文中的示例代碼講解詳細,對我們深入學習C#有一定的幫助,感興趣的小伙伴可以了解下

新的 C# 12 功能在預(yù)覽版中已經(jīng)引入. 您可以使用最新的 Visual Studio 預(yù)覽版或最新的 .NET 8 預(yù)覽版 SDK 來嘗試這些功能。以下是一些新引入的功能:

  • 主構(gòu)造函數(shù)
  • 集合表達式
  • 默認 Lambda 參數(shù)
  • 任何類型的別名
  • 內(nèi)聯(lián)數(shù)組
  • 攔截器
  • 使用nameof訪問實例成員

主構(gòu)造函數(shù)

現(xiàn)在可以在任何 class 和 struct 中創(chuàng)建主構(gòu)造函數(shù)。 主構(gòu)造函數(shù)不再局限于 record 類型。 主構(gòu)造函數(shù)參數(shù)都在類的整個主體的范圍內(nèi)。 為了確保顯式分配所有主構(gòu)造函數(shù)參數(shù),所有顯式聲明的構(gòu)造函數(shù)都必須使用 this() 語法調(diào)用主構(gòu)造函數(shù)。 將主構(gòu)造函數(shù)添加到 class 可防止編譯器聲明隱式無參數(shù)構(gòu)造函數(shù)。 在 struct 中,隱式無參數(shù)構(gòu)造函數(shù)初始化所有字段,包括 0 位模式的主構(gòu)造函數(shù)參數(shù)。

編譯器僅在 record 類型(record class 或 record struct 類型)中為主構(gòu)造函數(shù)參數(shù)生成公共屬性。 對于主構(gòu)造函數(shù)參數(shù),非記錄類和結(jié)構(gòu)可能并不總是需要此行為。

主構(gòu)造函數(shù)的參數(shù)位于聲明類型的整個主體中。 它們可以初始化屬性或字段。 它們可用作方法或局部函數(shù)中的變量。 它們可以傳遞給基本構(gòu)造函數(shù)。

主構(gòu)造函數(shù)指示這些參數(shù)對于類型的任何實例是必需的。 任何顯式編寫的構(gòu)造函數(shù)都必須使用 this(...) 初始化表達式語法來調(diào)用主構(gòu)造函數(shù)。 這可確保主構(gòu)造函數(shù)參數(shù)絕對由所有構(gòu)造函數(shù)分配。 對于任何 class 類型(包括 record class 類型),當主構(gòu)造函數(shù)存在時,不會發(fā)出隱式無參數(shù)構(gòu)造函數(shù)。 對于任何 struct 類型(包括 record struct 類型),始終發(fā)出隱式無參數(shù)構(gòu)造函數(shù),并始終將所有字段(包括主構(gòu)造函數(shù)參數(shù))初始化為 0 位模式。 如果編寫顯式無參數(shù)構(gòu)造函數(shù),則必須調(diào)用主構(gòu)造函數(shù)。 在這種情況下,可以為主構(gòu)造函數(shù)參數(shù)指定不同的值。

下面看下主構(gòu)造函數(shù)的應(yīng)用場景

初始化屬性

以下代碼初始化從主構(gòu)造函數(shù)參數(shù)計算的兩個只讀屬性:

public readonly struct Distance(double dx, double dy)
{
    public readonly double Magnitude = Math.Sqrt(dx * dx + dy * dy);
    public readonly double Direction = Math.Atan2(dy, dx);
}

前面的代碼演示了用于初始化計算的只讀屬性的主構(gòu)造函數(shù)。 Direction 和 Magnitude 的字段初始值設(shè)定項使用主構(gòu)造函數(shù)參數(shù)。 主構(gòu)造函數(shù)參數(shù)不會在結(jié)構(gòu)中的其他任何位置使用。 前面的結(jié)構(gòu)就像編寫了以下代碼一樣:

public readonly struct Distance
{
    public readonly double Magnitude { get; }
    public readonly double Direction { get; }
    public Distance(double dx, double dy)
    {
        Magnitude = Math.Sqrt(dx * dx + dy * dy);
        Direction = Math.Atan2(dy, dx);
    }
}

當需要參數(shù)來初始化字段或?qū)傩詴r,利用新功能可以更輕松地使用字段初始值設(shè)定項。

創(chuàng)建可變狀態(tài)

前面的示例使用主構(gòu)造函數(shù)參數(shù)來初始化只讀屬性。 如果屬性不是只讀的,你還可以使用主構(gòu)造函數(shù)。 考慮下列代碼:

public struct Distance(double dx, double dy)
{
    public readonly double Magnitude => Math.Sqrt(dx * dx + dy * dy);
    public readonly double Direction => Math.Atan2(dy, dx);
    public void Translate(double deltaX, double deltaY)
    {
        dx += deltaX;
        dy += deltaY;
    }
    public Distance() : this(0,0) { }
}

在前面的示例中,Translate 方法了更改 dx 和 dy 組件。 這就需要在訪問時計算 Magnitude 和 Direction 屬性。 => 運算符指定一個以表達式為主體的 get 訪問器,而 = 運算符指定一個初始值設(shè)定項。 此版本將無參數(shù)構(gòu)造函數(shù)添加到結(jié)構(gòu)。 無參數(shù)構(gòu)造函數(shù)必須調(diào)用主構(gòu)造函數(shù),以便初始化所有主構(gòu)造函數(shù)參數(shù)。

依賴關(guān)系注入

主構(gòu)造函數(shù)的另一個常見用途是指定依賴項注入的參數(shù)。 下面的代碼創(chuàng)建了一個簡單的控制器,使用時需要有一個服務(wù)接口:

public interface IService
{
    Distance GetDistance();
}
public class ExampleController(IService service) : ControllerBase
{
    [HttpGet]
    public ActionResult<Distance> Get()
    {
        return service.GetDistance();
    }
}

主構(gòu)造函數(shù)清楚地指明了類中所需的參數(shù)。 使用主構(gòu)造函數(shù)參數(shù)就像使用類中的任何其他變量一樣。

初始化基類

可以從派生類的主構(gòu)造函數(shù)調(diào)用基類的主構(gòu)造函數(shù)。 這是編寫必須調(diào)用基類中主構(gòu)造函數(shù)的派生類的最簡單方法。 例如,假設(shè)有一個類的層次結(jié)構(gòu),將不同的帳戶類型表示為一個銀行。 基類類似于以下代碼:

public class BankAccount(string accountID, string owner)
{
    public string AccountID { get; } = accountID;
    public string Owner { get; } = owner;
    public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}";
}

一個派生類將呈現(xiàn)一個支票帳戶:

public class CheckAccount(string accountID, string owner, decimal overdraftLimit = 0) : BankAccount(accountID, owner)
{
    public decimal CurrentBalance { get; private set; } = 0;
    public void Deposit(decimal amount)
    {
        if (amount < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Deposit amount must be positive");
        }
        CurrentBalance += amount;
    }
    public void Withdrawal(decimal amount)
    {
        if (amount < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(amount), "Withdrawal amount must be positive");
        }
        if (CurrentBalance - amount < -overdraftLimit)
        {
            throw new InvalidOperationException("Insufficient funds for withdrawal");
        }
        CurrentBalance -= amount;
    }
    public override string ToString() => $"Account ID: {AccountID}, Owner: {Owner}, Balance: {CurrentBalance}";
}

總結(jié)

通過合理有效地利用主構(gòu)造函數(shù),我們可以創(chuàng)造出更靈活、更強大、更可控的代碼構(gòu)造。

集合表達式

集合表達式引入了新的語法來創(chuàng)建常見的集合值。 可以使用展開運算符 .. 將其他集合內(nèi)聯(lián)到這些值中。

以下示例演示了集合表達式的使用:

// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Create a span
Span<int> b  = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// Create a 2 D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
// create a 2 D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];

總結(jié)

集合表達式使得代碼更簡潔,操作更便捷。

默認 Lambda 參數(shù)

現(xiàn)在可以為 Lambda 表達式的參數(shù)定義默認值。 語法和規(guī)則與將參數(shù)的默認值添加到任何方法或本地函數(shù)相同。

Func<int, string, bool> isTooLong = (int x, string s = "") => s.Length > x;

總結(jié)

默認 Lambda 參數(shù),彌補了Lambda不能設(shè)置默認參數(shù)的缺陷。

任何類型的別名

可以使用 using 別名指令創(chuàng)建任何類型的別名,而不僅僅是命名類型。 這意味著可以為元組類型、數(shù)組類型、指針類型或其他不安全類型創(chuàng)建語義別名。

using Point = (int x, int y);

總結(jié)

它提供了一個簡短的,由開發(fā)者提供的名稱,可以用來替代那些完整的結(jié)構(gòu)形式。

內(nèi)聯(lián)數(shù)組(Inline Arrays)

運行時團隊和其他庫作者使用內(nèi)聯(lián)數(shù)組來提高應(yīng)用的性能。 內(nèi)聯(lián)數(shù)組使開發(fā)人員能夠創(chuàng)建固定大小的 struct 類型數(shù)組。 具有內(nèi)聯(lián)緩沖區(qū)的結(jié)構(gòu)應(yīng)提供類似于不安全的固定大小緩沖區(qū)的性能特征。 你可能不會聲明自己的內(nèi)聯(lián)數(shù)組,但當它們從運行時 API 作為 System.Span 或 System.ReadOnlySpan 對象公開時,你將透明地使用這些數(shù)組。

內(nèi)聯(lián)數(shù)組的聲明類似于以下 struct:

[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
    private int _element0;
}

它們的用法與任何其他數(shù)組類似:

var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
    buffer[i] = i;
}
foreach (var i in buffer)
{
    Console.WriteLine(i);
}

區(qū)別在于編譯器可以利用有關(guān)內(nèi)聯(lián)數(shù)組的已知信息。 你可能會像使用任何其他數(shù)組一樣使用內(nèi)聯(lián)數(shù)組。

總結(jié)

內(nèi)聯(lián)數(shù)組對性能提高幫助很大。

攔截器(Interceptors)

警告:本次發(fā)布的預(yù)覽版引入了一項叫做interceptors(攔截器)的新功能。這項新功能主要用于一些高級場景,尤其是將會帶來更好的AOT編譯能力。作為.NET 8的實驗性功能,在未來的版本中有可能被修改甚至刪除,因此,它不應(yīng)該在生產(chǎn)環(huán)境中使用。

攔截器是一種方法,該方法可以在編譯時以聲明方式將對可攔截方法的調(diào)用替換為對其自身的調(diào)用。 通過讓攔截器聲明所攔截調(diào)用的源位置,可以進行這種替換。 此過程可以向編譯中(例如在源生成器中)添加新代碼,從而提供更改現(xiàn)有代碼語義的有限能力。

在源生成器中使用攔截器修改現(xiàn)有編譯的代碼,而非向其中添加代碼。 源生成器將對可攔截方法的調(diào)用替換為對攔截器方法的調(diào)用。

總結(jié)

攔截器很強大,進一步了解可以參考下面連接:https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md

使用nameof訪問實例成員

曾經(jīng)為了訪問實例成員,你頻繁地編寫nameof感到非常惱火嗎?好消息是,C# 12 Preview 3為你帶來解決方案。讓我們一起看看這個神奇的功能是如何工作的:
記得以前,當嘗試使用nameof關(guān)鍵字去訪問一個實例字段時,你必須有一個對象的實例,對吧?

現(xiàn)在,告別這些限制吧!有了C# 12 Preview 3,我們只需要類就可以做到這一點。

給出一個實際的例子,讓我們看看這個獨特的特性在這段代碼中是如何發(fā)揮作用的:

internal class NameOf
{
    public string S { get; } = "";
    public static int StaticField;
    public string NameOfLength { get; } = nameof(S.Length);
    public static void NameOfExamples()
    {
        Console.WriteLine(nameof(S.Length));       // 使用`nameof`訪問實例成員
        Console.WriteLine(nameof(StaticField.MinValue));  // 使用`nameof`訪問靜態(tài)字段
    }
    [Description($"String {nameof(S.Length)}")]
    public int StringLength(string s)
    { return s.Length; }
}

你看到nameof如何處理S.Length 和 StaticField.MinValue了嗎?這是C# 12 Preview 3的新特性!你不需要一個實例就可以獲取S.Length的名稱。你也可以用nameof獲取StaticField.MinValue。

簡單來說,想象你有一個叫做"NameOf"的玩具盒。以前,你必須爬進盒子里才能找到你最喜歡的玩具。

但現(xiàn)在呢?你只需要告訴你的魔術(shù)盒你想要什么(比如,你想要的玩具魔方的長度,或者芭蕾舞泰迪熊的最小數(shù)量),它就會給你,都不用進去!

總結(jié)

nameof的增強,讓代碼更少,邏輯更簡單。

參考文檔:https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12

以上就是C#12中的新增功能使用總結(jié)的詳細內(nèi)容,更多關(guān)于C#12新增功能的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論