C#9.0中init訪問器的實現(xiàn)
不控制可變性
下面是我們最常見的屬性聲明方式,允許屬性在類的內(nèi)部和外部都可以讀取和修改
public int Id { get; set; }
namespace Demo
{
public class Company
{
public int Id { get; set; }
public Company()
{
}
public Company(int id)
{
Id = id; // 可以在構(gòu)造函數(shù)中設(shè)置
}
public void UpdateId(int newId)
{
Id = newId; // 可以在類內(nèi)部的方法中修改
}
}
internal class Program
{
static void Main(string[] args)
{
var company = new Company(1);
Console.WriteLine(company.Id); // 輸出:1
company.Id = 2; // 可以在類外部修改
Console.WriteLine(company.Id); // 輸出:2
// 使用對象初始化器語法,需要無參數(shù)構(gòu)造函數(shù)
var newCompany = new Company { Id = 6 };
Console.WriteLine(newCompany.Id); // 輸出:6
newCompany.UpdateId(4); // 通過方法更新
Console.WriteLine(newCompany.Id); // 輸出:4
}
}
}
數(shù)據(jù)一致性問題:在某些情況下,屬性不應(yīng)該在對象生命周期內(nèi)被隨意修改。例如,Id屬性通常用于唯一標識一個對象,如果允許在對象生命周期內(nèi)修改它,可能導致數(shù)據(jù)不一致的問題
去掉set訪問器
去掉set訪問器,使得屬性變?yōu)橹蛔x
namespace Demo
{
public class Company
{
public int Id { get; }
public Company()
{
}
public Company(int id)
{
Id = id; // 只能在構(gòu)造函數(shù)中設(shè)置
}
// UpdateId 方法不能再修改 Id 屬性,因為 get 訪問器限制了修改
// public void UpdateId(int newId)
// {
// Id = newId; // 編譯錯誤:不能修改只讀屬性
// }
}
internal class Program
{
static void Main(string[] args)
{
var company = new Company(1);
Console.WriteLine(company.Id); // 輸出:1
// 下面這行代碼會導致編譯錯誤,因為 Id 屬性是只讀的
// company.Id = 2; // 編譯錯誤:不能修改只讀屬性
// 下面這行代碼會導致編譯錯誤,因為對象初始化器不能設(shè)置只讀屬性
// var newCompany = new Company { Id = 6 }; // 編譯錯誤:不能使用對象初始化器設(shè)置只讀屬性
var newCompany = new Company(6);
Console.WriteLine(newCompany.Id); // 輸出:6
// newCompany.UpdateId(4); // 編譯錯誤:不能修改只讀屬性
// Console.WriteLine(newCompany.Id); // 輸出:4
}
}
}
readonly
readonly指示只能在聲明期間或在同一個類的構(gòu)造函數(shù)中向字段賦值。 可以在字段聲明和構(gòu)造函數(shù)中多次分配和重新分配只讀字段
namespace Demo
{
public class Company
{
public readonly int Id = 666; // 使用 readonly 關(guān)鍵字,初始化默認值為 666
public Company()
{
// 無參數(shù)構(gòu)造函數(shù)使用默認值 666
}
public Company(int id)
{
Id = id; // 可以在構(gòu)造函數(shù)中設(shè)置新的值
}
// UpdateId 方法不能再修改 Id 字段,因為 readonly 限制了修改
// public void UpdateId(int newId)
// {
// Id = newId; // 編譯錯誤:readonly 字段只能在構(gòu)造函數(shù)中賦值
// }
}
internal class Program
{
static void Main(string[] args)
{
var initCompany = new Company();
Console.WriteLine(initCompany.Id); // 輸出:666
var company = new Company(1);
Console.WriteLine(company.Id); // 輸出:1
// 下面這行代碼會導致編譯錯誤,因為 Id 字段是只讀的
// company.Id = 2; // 編譯錯誤:readonly 字段在構(gòu)造函數(shù)外不可修改
// 使用對象初始化器時不能設(shè)置 readonly 字段,因此需要使用構(gòu)造函數(shù)
// var newCompany = new Company { Id = 6 }; // 編譯錯誤:readonly 字段不能使用對象初始化器設(shè)置
}
}
}
private
如果不想在類外部修改,我們也可以這樣寫
namespace Demo
{
public class Company
{
public int Id { get; private set; }
public Company() { }
public Company(int id)
{
Id = id; // 可以在構(gòu)造函數(shù)中設(shè)置
}
public void UpdateId(int newId)
{
Id = newId; // 可以在類內(nèi)部的方法中修改
}
}
internal class Program
{
static void Main(string[] args)
{
var company = new Company(1);
Console.WriteLine(company.Id); //輸出:1
company.UpdateId(4);
Console.WriteLine(company.Id); // 輸出:4
var newCompany = new Company();
//company.Id = 2; // 編譯錯誤:外部不能修改
}
}
}
private set訪問器,允許類內(nèi)部修改屬性,但外部不可修改,即保護內(nèi)部狀態(tài),常見應(yīng)用場景:計數(shù)器、狀態(tài)管理等
init訪問器
init訪問器允許屬性在對象初始化時設(shè)置,但在對象初始化完成后就不能再修改
using System;
namespace Demo
{
public class Company
{
public int Id { get; init; } // 使用 init 訪問器,使得屬性在初始化后不可修改
public Company()
{
}
public Company(int id)
{
Id = id; // 可以在構(gòu)造函數(shù)中設(shè)置
}
// UpdateId 方法不能再修改 Id 屬性,因為 init 訪問器限制了修改
// public void UpdateId(int newId)
// {
// Id = newId; // 編譯錯誤:初始化后不可修改
// }
}
internal class Program
{
static void Main(string[] args)
{
var company = new Company(1);
Console.WriteLine(company.Id); // 輸出:1
// 下面這行代碼會導致編譯錯誤,因為 Id 屬性是只讀的
// company.Id = 2; // 編譯錯誤:初始化后不可修改
var newCompany = new Company { Id = 3 }; // 使用對象初始化器
Console.WriteLine(newCompany.Id); // 輸出:3
// 下面這行代碼會導致編譯錯誤,因為 Id 屬性是只讀的
// newCompany.Id = 4; // 編譯錯誤:初始化后不可修改
}
}
}
init訪問器在數(shù)據(jù)傳輸對象(DTO)和配置對象中的應(yīng)用
數(shù)據(jù)傳輸對象(DTO)
數(shù)據(jù)傳輸對象(DTO)是用于在不同系統(tǒng)或不同層之間傳遞數(shù)據(jù)的簡單對象。這些對象通常不包含任何業(yè)務(wù)邏輯,僅用于封裝數(shù)據(jù)。使用init訪問器可以確保DTO在創(chuàng)建后其屬性不會被修改,從而保證傳輸數(shù)據(jù)的完整性和一致性
namespace Demo
{
public class CustomerDto
{
public int Id { get; init; }
public string Name { get; init; }
public string Email { get; init; }
}
internal class Program
{
static void Main(string[] args)
{
// 使用對象初始化器創(chuàng)建DTO實例
var customer = new CustomerDto
{
Id = 1,
Name = "John Doe",
Email = "john.doe@example.com"
};
Console.WriteLine($"Customer: {customer.Id}, {customer.Name}, {customer.Email}"); // 輸出:Customer: 1, John Doe, john.doe@example.com
// customer.Name = "Jane Doe"; // 編譯錯誤:初始化后不可修改
}
}
}
配置對象
配置對象通常用于存儲應(yīng)用程序的配置設(shè)置。這些設(shè)置在應(yīng)用程序啟動時加載,并在整個應(yīng)用程序生命周期內(nèi)保持不變。使用init訪問器可以確保配置對象在初始化后,其配置屬性不會被修改,從而防止在應(yīng)用程序運行過程中意外更改配置
public class AppConfig
{
public string ConnectionString { get; init; }
public int MaxRetryCount { get; init; }
public bool EnableLogging { get; init; }
}
internal class Program
{
static void Main(string[] args)
{
// 使用對象初始化器創(chuàng)建配置對象實例
var config = new AppConfig
{
ConnectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;",
MaxRetryCount = 5,
EnableLogging = true
};
// 輸出:Config: ConnectionString=Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;, MaxRetryCount=5, EnableLogging=True
Console.WriteLine($"Config: ConnectionString={config.ConnectionString}, MaxRetryCount={config.MaxRetryCount}, EnableLogging={config.EnableLogging}");
// config.MaxRetryCount = 10; // 編譯錯誤:初始化后不可修改
}
}
開始使用init訪問器
在C#9.0中,引入了init訪問器。使用此功能,有兩個先決條件:
- 安裝.NET 5+ SDK
- 安裝Visual Studio 2019或更高版本
參考
- C# Init-Only Setters 屬性 — C# Init-Only Setters Property (loginradius.com)
- C#中init()方法是起什么作用啊-CSDN社區(qū)
- init 關(guān)鍵字 - C# reference | Microsoft Learn
- 一看就懂——C#中readonly關(guān)鍵字_c# readonly關(guān)鍵字-CSDN博客
- 只讀關(guān)鍵字 - C# reference | Microsoft Learn
- C#9.0:Init - Hello-Brand - 博客園 (cnblogs.com)
到此這篇關(guān)于C#9.0中init訪問器的實現(xiàn)的文章就介紹到這了,更多相關(guān)C# init訪問器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用?FieldMask?提高?C#?gRpc?的服務(wù)性能
這篇文章主要介紹了用?FieldMask?提高?C#?gRpc?的服務(wù)性能,FieldMask?是一個?protobuf?消息,包含一個名為?paths?的字段,用于指定用于指定讀取操作返回或更新操作修改的字,下文詳細內(nèi)容,需要的朋友可以參考一下2022-03-03
C#使用Post調(diào)用接口并傳遞json參數(shù)
這篇文章主要介紹了C#使用Post調(diào)用接口并傳遞json參數(shù),具有很好的參考價值,希望對大家有所幫助。2022-06-06

