結構struct成員支持readonly,用來限制被其修飾的成員不會改變結構的內部狀態。加上7.2版本添加的readonly struct和ref readonly方法返回以及之前的欄位聲明修飾作用,現在readonly一共有四種修飾作用。下麵兩段代碼以及註釋進行了說明。 //(v8.0)reado ...
結構struct成員支持readonly,用來限制被其修飾的成員不會改變結構的內部狀態。加上7.2版本添加的readonly struct和ref readonly方法返回以及之前的欄位聲明修飾作用,現在readonly一共有四種修飾作用。下麵兩段代碼以及註釋進行了說明。
//(v8.0)readonly成員: //1. 只對struct成員有效,指示該成員不會修改結構的內部狀態。如果該成員直接修改狀態或者訪問未使用readonly修飾的成員,則結果會報錯。 //2. 不能用於靜態成員和構造函數。 public struct MutablePerson { private static readonly MutablePerson _origin = new MutablePerson(); //結構中靜態欄位即可聲明也可初始化 //---------start ref readonly--------------- public static ref readonly MutablePerson Origin => ref _origin;//由ref readonly返回的引用,調用方無法修改來源。註意此是個屬性 //public static ref readonly MutablePerson NewOne; //ref readonly 只能用於方法或者屬性,不能用於欄位。 //---------end ref readonly--------------- public static int Population = 100; private float _maxAge; public string Name; // 結構中欄位只能在此聲明,不能初始化 public int Age { get; set; }//結構中自動屬性只能在此聲明,不能初始化。 //public int Age { readonly get; set; } public float Height { readonly get; //readonly可以添加到屬性或者索引的單個get或者set訪問器中。但同時不能再給屬性上有readonly修飾符 set; } readonly public string Nationality { get;} //readonly修飾的自動屬性不能有set訪問器。與下麵註釋的代碼等效 //public string Nationality { readonly get; } //public string Nationality { readonly get{return _nationality;} set{}} string _nationality; readonly public float MaxAge{ get { return _maxAge; } set { } // 沒有用,但是合法 } ////結構中不能包含顯式的無參構造函數,編譯器會自動創建 //public Point() //{ // Name = null; // Age = 0; // Height = 0; //} public MutablePerson(string name):this(name,0) { ////每個構造函數中必須對所有未初始化的欄位和自動屬性進行初始化 Height = 0.5f; Nationality = "CHINA"; _maxAge = 100; } public MutablePerson(string name, int age):this(name,age,0.5f) => (Nationality,_maxAge) = ("CHINA",100);//每個構造函數中必須對所有未初始化的欄位和自動屬性進行初始化 public MutablePerson(string name, int age, float height) => (Name, Age, Height, Nationality, _maxAge) = (name, age, height, "CHINA", 100);//每個構造函數中必須對所有未初始化的欄位和自動屬性進行初始化 public MutablePerson(MutablePerson other) { this = other; } public MutablePerson Replace(MutablePerson other) { this = other; return other; } public void Increase(int ageOffset, float heightOffset) //此成員不能用readonly修飾,因為裡面代碼會改變成員狀態。 { Age += ageOffset; Height += heightOffset; } // readonly 成員中沒有對狀態欄位和屬性的任何修改 public readonly string SayHello => $"Hello, my name is {Name}, I am {Age} and my height is {Height}"; //readonly函數訪問未標記為readonly的SayHello方法時,會發出創建防禦性副本的警告。 public readonly override string ToString() => $"(Name:{Name}, Age:{Age}, Height:{Height}),{SayHello}"; }
//(v7.2)readonly struct 指示Point是不可變的。有如下限制: //1.該結構中每個欄位和屬性都是readonly //2.需要公共構造函數初始化成員 //3.this也是readonly,只能再構造函數中進行初始化賦值 //4.不能定義像欄位樣子的事件 public readonly struct ReadonlyPerson { private static readonly ReadonlyPerson _origin = new ReadonlyPerson(); //結構中靜態欄位即可聲明也可初始化 public static ref readonly ReadonlyPerson Origin => ref _origin; //由ref readonly返回的引用,調用方無法修改來源。註意此是個屬性 public static int Population = 100; //readonly struct對靜態欄位沒有效用,不必指定readonly public readonly string Name; // 必須給readonly struct中的欄位指定readonly。結構中欄位只能在此聲明,不能初始化 public int Age { get; }//不能有set訪問器,且只讀自動屬性指示編譯器為這些屬性創建readonly的支持欄位。結構中自動屬性只能在此聲明,不能初始化 public float Height { get; } //不能有set訪問器,且只讀自動屬性指示編譯器為這些屬性創建readonly的支持欄位。結構中自動屬性只能在此聲明,不能初始化 ////結構中不能包含顯式的無參構造函數,編譯器會自動創建 //public ReadonlyPerson() //{ // Name = null; // Age = 0; // Height = 0; //} public ReadonlyPerson(string name):this(name,0) { Height = 0.5f; //必須在此初始化,沒有參數必須初始化為預設值,不能在結構聲明中初始化 } public ReadonlyPerson(string name, int age) : this(name, age, 0.5f) { }//每個構造函數中必須對所有未初始化的欄位和自動屬性進行初始化 public ReadonlyPerson(string name, int age, float height) => (Name, Age, Height) = (name, age, height);//每個構造函數中必須對所有未初始化的欄位和自動屬性進行初始化 public ReadonlyPerson(ReadonlyPerson other) { this = other;//可以用另一個對象來初始化。 } public MutablePerson Replace(MutablePerson other) { //this = other; //this是readonly,不能被修改。 //this.Age = other.Age;//this是readonly,他的成員也是不能被修改。 return other; } public void Increase(int ageOffset, float heightOffset) { //Age += ageOffset; //Age在readonly struct中是只讀的,因此在這裡不能被賦值。 //Height += heightOffset; //Height在 readonly struct中是只讀的,因此在這裡不能被賦值。 } // 該成員中沒有對狀態欄位和屬性的任何修改 public string SayHello => $"Hello, my name is {Name}, I am {Age} and my height is {Height}"; //該函數不能給本結構中的任何欄位和屬性做出修改 public override string ToString() => $"(Name:{Name}, Age:{Age}, Height:{Height}),{SayHello}"; }