关键词搜索

源码搜索 ×
×

C#8.0中新特性之一:结构readonly成员及其相关特性

发布2020-12-14浏览324次

详情内容

  在C#8.0中,结构(struct)引入了一项新特性,就是使其成员支持readonly(只读),这个特性用来限制被其修饰的成员不会改变结构的内部状态。这项特性,与C#7.2版本添加的readonly struct和ref readonly方法返回、及C#原本之前的只读字段声明修饰作用一起,共同组成了目前readonly的四种修饰作用。

    一、readonly只读成员的主要作用

      如前所述,就是被修饰的成员不会改变或者修改结构的内部状态。
    

      二、readonly只读成员规则与限制

      只对结构(struct)的成员有效,不能用于类,指示该成员不会修改结构的内部状态。如果该成员直接修改状态或者访问未使用readonly修饰的成员,则结果会报错。

      不能用于静态成员和构造函数。

      readonly修饰的自动属性不能有set访问器。

      readonly添加到属性或者索引的单个get访问器中。但同时不能在属性上有readonly修饰符

      readonly函数访问未标记为readonly的成员时,会发出创建防御性副本的警告。

      三、Readonly只读成员的示例代码:

      复制代码
      //(C# 8.0)结构readonly成员规则及示例:
      //1. 只对结构(struct)的成员有效,不能用于类,指示该成员不会修改结构的内部状态。如果该成员直接修改状态或者访问未使用readonly修饰的成员,则结果会报错。
      /https://cdn.jxasp.com:9143/image/2. 不能用于静态成员和构造函数。
      //3. readonly修饰的自动属性不能有set访问器。
      //4. readonly添加到属性或者索引的单个get访问器中。但同时不能在属性上有readonly修饰符
      //5. readonly函数访问未标记为readonly的成员时,会发出创建防御性副本的警告。

      public struct MutablePerson
      {
          //结构中静态字段即可声明也可初始化
          private static readonly MutablePerson _origin = new MutablePerson();
      
          //此属性由ref readonly返回的引用,调用方无法修改来源
          public static ref readonly MutablePerson Origin => ref _origin;
      
          //ref readonly 只能用于方法或者属性,不能用于字段。
          //public static ref readonly MutablePerson NewOne; 
      
          // 结构中字段只能声明,不能初始化,静态字段除外
          public static int Population = 100;
          private float _maxAge;
          public string Name;
      
          //结构中自动属性只能在此声明,不能初始化。
          //此自动属性不能在属性外添加readonly,因为其中含有set访问器
          public int Age { get; set; }
          //public readonly int Age { get; set; }
      
          public float Height {
              //readonly可以添加到属性或者索引的单个get访问器中。但同时不能再给属性上有readonly修饰符
              readonly get; 
              set; }
      
          //readonly修饰的自动属性不能有set访问器。与下面注释的代码等效
          readonly public string Nationality { get;}
          //public string Nationality { readonly get; }                                           
          //string _nationality;
          //public string Nationality { readonly get { return _nationality; } set { } }
      
          readonly public float MaxAge{
              get { return _maxAge; }
              set { } // 没有用,但是合法
          }
      
      
          结构中不能包含显式的无参构造函数,编译器会自动创建
          //public MutablePerson()
          //{
          //    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;
          }
      
          //此成员不能用readonly修饰,因为里面代码会改变成员状态。
          public void Increase(int ageOffset, float heightOffset) 
          {
              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}";
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86

      四、其他readonly struct等非8.0相关特性说明

      C#7.2 readonly struct 指示结构是不可变的。有如下限制:

      该结构中每个字段和属性都是readonly

      需要公共构造函数初始化成员

      this也是readonly,只能在构造函数中进行初始化赋值

      不能定义像字段样子的事件

      ref readonly用来指示返回c#教程的引用,调用方无法修改来源。而readonly修饰的字段,指示该字段在被初始化后,不能再被修改。

      具体示例代码如下:

      //(C#7.2) readonly struct 指示结构是不可变的。有如下限制:
      //1.该结构中每个字段和属性都是readonly
      /https://cdn.jxasp.com:9143/image/2.需要公共构造函数初始化成员
      //3.this也是readonly,只能在构造函数中进行初始化赋值
      //4.不能定义像字段样子的事件
      public readonly struct ReadonlyPerson
      {
          //结构中静态字段即可声明也可初始化
          private static readonly ReadonlyPerson _origin = new ReadonlyPerson();
      
          //由ref readonly返回的引用,调用方无法修改来源。注意此是个属性
          public static ref readonly ReadonlyPerson Origin => ref _origin;
      
          //readonly struct对静态字段没有效用,不必指定readonly
          public static int Population = 100;
      
          // 必须给readonly struct中的字段指定readonly。结构中字段只能在此声明,不能初始化
          public readonly string Name;
      
          //不能有set访问器,且只读自动属性指示编译器为这些属性创建readonly的支持字段。结构中自动属性只能在此声明,不能初始化
          public int Age { get; }
      
          //不能有set访问器,且只读自动属性指示编译器为这些属性创建readonly的支持字段。结构中自动属性只能在此声明,不能初始化
          public float Height { get; } 
      
          结构中不能包含显式的无参构造函数,编译器会自动创建
          //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}";
      
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72

      五、结束语

      至此,有关struct相关的readonly的四种修饰及其python基础教程
      用法的介绍就到这里,因水平有限,如有错误或不妥指出,请指正。

      作者:MarkKang
      出处:https://www.cnblogs.com/markkang/

      相关技术文章

      点击QQ咨询
      开通会员
      返回顶部
      ×
      微信扫码支付
      微信扫码支付
      确定支付下载
      请使用微信描二维码支付
      ×

      提示信息

      ×

      选择支付方式

      • 微信支付
      • 支付宝付款
      确定支付下载