C#8.0中新特性之一:結構readonly成員

  結構struct成員支持readonly,用來限制被其修飾的成員不會改變結構的內部狀態。加上7.2版本添加的readonly struct和ref readonly方法返回以及以前的字段聲明修飾做用,如今readonly一共有四種修飾做用。下面兩段代碼以及註釋進行了說明。ide

    //(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}";

    }
相關文章
相關標籤/搜索