在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/