欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#8.0中新特性之一:结构readonly成员

程序员文章站 2023-11-14 13:36:04
结构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}";

    }