readonly 可以在下述上下文中使用。

字段声明

在字段声明中,readonly 指示只能在字段声明方法或在同一个类的构造函数中向字段赋值(甚至可以多次赋值)。可以在字段声明和构造函数中多次分配和重新分配只读字段。

声明方法或构造函数退出后,不能分配 readonly 字段。此规则对于值类型和引用类型具有不同的含义:

  • 由于值类型直接包含数据,因此属于 readonly 值类型的字段不可变。
  • 由于引用类型包含对其数据的引用,因此属于 readonly 引用类型的字段只是必须始终引用同一对象而已。该对象可能是可变的。readonly 修饰符可防止将字段值替换为引用类型的其他实例。但是,修饰符不会阻止通过只读字段修改字段的实例数据。

警告:包含属于可变引用类型的外部可见只读字段的外部可见类型可能存在安全漏洞,可能会触发警告 CA2104:“不要声明只读可变引用类型。”

在 readonly 结构类型定义中,只读表示该结构类型是不可变的。

在结构类型中的实例成员声明中,readonly 表示实例成员不修改结构的状态。

在 ref readonly 方法返回中,readonly 修饰符指示方法返回一个引用,并且不允许对该引用进行写操作。

  • 为方法声明一个 ref readonly 形参。

示例

{
    static void Main ( string [ ] args )
        {
            Lei年龄 wo = new ( new ( 1930 , 3 , 11 ) );
            Console . WriteLine( wo . 年龄 );
        }
}

public class Lei年龄
    {
        private DateTime _生日;
        private readonly int Z年龄;

        public Lei年龄 ( DateTime 生日 )
            {
                _生日 = 生日;

                // 在构造函数中可以为 readonly 字段赋值
                Z年龄 = ( DateTime . Now - _生日 ) . Days / 365;
            }

        public int 年龄
            {
            get => Z年龄;
            // set => Z年龄 = value; // 警告 CS0191:无法分配到只读字段(除非在定义了该字段的类型的构造函数或 init-only 资源库中,或者在变量初始值设定项中)
            }
    }

只能在下列上下文中对 readonly 字段进行赋值:

  • 在声明中初始化变量时,例如:
    public readonly int y = 5;
  • 在包含实例字段声明的类的实例构造函数中。
  • 在包含 static 字段声明的类的 static 构造函数中。

只有在这些构造函数上下文中,将 readonly 字段作为 out 或 ref 参数传递才有效。

备注:readonly 关键字不同于 const 关键字。const 字段只能在该字段的声明中初始化。可以在字段声明和任何构造函数中多次分配 readonly 字段。因此,根据所使用的构造函数,readonly 字段可能具有不同的值。另外,虽然 const 字段是编译时常量,但 readonly 字段可用于运行时常量,如下面的示例所示:
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;

{
    static void Main ( string [ ] args )
        {
            LeiGou wc = new ( );
            wc . _名字 = "旺财"; // 对于“旺财”只有它的名字是可以改的;年龄永远是 0;叫声永远是“汪”
            // wc . _年龄 = 4; // 警告 CS0191:无法分配到只读字段(除非在定义了该字段的类型的构造函数或 init-only 资源库中,或者在变量初始值设定项中)
            Console . WriteLine ( $"名字:{wc . _名字};年龄:{wc . _年龄};叫声:{wc . _叫声}" );

            LeiGou lf = new ( "来福" , 3 , "噢" ); // 这个“来福”应该是只狼
            Console . WriteLine ( $"名字:{lf . _名字};年龄:{lf . _年龄};叫声:{lf . _叫声}" );
        }
    }

public class LeiGou
    {
        public string _名字;
        public readonly int _年龄;
        public readonly string _叫声;

        public LeiGou ( )
            {
                _叫声 = "汪";
            }

        public LeiGou ( string 名字 , int 年龄 , string 叫声 )
            {
                _名字 = 名字;
                _年龄 = 年龄;
                _叫声 = 叫声;
            }
        }

readonly 实例成员

还可以使用 readonly 修饰符来声明实例成员不会修改结构的状态。

public readonly double 总和 ( )
{
    return X + Y;
}

备注:对于读/写属性,可以将 readonly 修饰符添加到 get 访问器。某些 get 访问器可以执行计算并缓存结果,而不是只返回专用字段的值。将 readonly 修饰符添加到 get 访问器可确保 get 访问器不会通过缓存任何结果来修改对象的内部状态。

引用 readonly 返回

ref return 上的 readonly 修饰符指示返回的引用无法修改。 下面的示例返回了一个对来源的引用。 它使用 readonly 修饰符来指示调用方无法修改来源:

private static readonly SamplePoint s_origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref s_origin;

返回的类型不需要是 readonly struct。任何可以用 ref 返回的类型都可以用 ref readonly 返回。

Readonly ref 返回示例

ref readonly 返回也可以用于 struct 类型上的 readonly 实例成员:

public struct ReadonlyRefReadonlyExample
    {
        private int _data;

        public readonly ref readonly int ReadonlyRefReadonly ( ref int reference )
        {
            // _data = 1; // Compile error if uncommented.
            return ref reference;
        }
}

该方法实际上返回一个 readonly ref,并且实例成员(在本例中是一个方法)是 readonly 的(不能修改任何实例字段)。


兔子码农
4 声望1 粉丝

一个酒晕子


« 上一篇
C# 的 public
下一篇 »
C# 的 ref