C# 6.0 基础知识:只读自动属性

对于不可变类型(immutable types),我们可以通过只读自动属性来创建(read-only auto-properties),也就是对属性只设置 get 访问器:

public string FirstName { get; }
public string LastName { get;  }

此时,FirstNameLastName 仅能在类的构造器方法中才能赋值:

public Student(string firstName, string lastName)
{
    if (IsNullOrWhiteSpace(lastName))
        throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
    FirstName = firstName;
    LastName = lastName;
}

如果在其他方法中尝试对只读自动属性赋值,那么就会产生 CS0200 编译时错误:

public class Student
{
    public string LastName { get;  }

    public void ChangeName(string newLastName)
    {
        // Generates CS0200: Property or indexer cannot be assigned to -- it is read only
        LastName = newLastName;
    }
}

介绍完了新增的只读自动属性,接下来该说一说与之容易混淆的 constreadonly 了。

const

const 修饰符作用于字段或变量之上,表示修饰的字段或变量包含的值是个常量,不能改变的。它的约束发生于编译时,而不是运行时,换句话说,也就是在应用 const 修饰符的时候就需要同时给它赋值。有个地方需要注意,声明了 const 的字段会自动变为 static 字段,提升到类级别之上。其实这也是很好理解的,因为在编译时就固定下来的值,运行时就无法改变,没必后期为每个实例都开辟空间存放这个固定不变的值。但是也很奇怪,如果某个字段声明为了 const,就无法继续声明为了 static,不然编译会发生 CS0504 错误,我个人觉得其实继续显式声明本无可厚非,大家使用的时候注意点,明白就好。

class ConvertUnits
{
    public const float CentimetersPerInch = 2.54F;
    public const int CupsPerGallon = 16;
    // ...
}

还有一点需要注意,const 字段只能够应用于那些具有字面量值类型的字段上(比如:string, int, double 等),Program 或者 System.Guid 这样的类型是不行的。

除了上面说到的 const 字段会自动转变为 static 字段这样的优化之外,针对它还有另一个优化:程序集的引用。如果一个程序集引用了另外一个程序集中的 const,那么被引用的程序集中的 const 会直接编译到引用的程序集中,那么,如果后期被引用的程序集中的 const 值发生了变化,而引用程序集没有继续对其进行编译,则这个引用程序集引用中的 const 值不会发生,除非对这个程序集重新编译。所以,const 修饰的值最好是那些始终不会变化的值,比如:PI。

readonly

接下来该着重说一下 readonly 了,先列出它和 const 的几点区别:

  1. readonly 修饰符仅能应用于字段上(不能应用于本地变量)
  2. readonly 修饰符不仅可以在字段声明的时候赋值,还可以在构造器方法中对其修饰的字符进行赋值(赋值发生于运行时而非编译时)
  3. 鉴于第 2 条区别,readonly 修饰的字段不仅可以作为实例级别的,也可以作为类级别的(显式使用 static 修饰)
  4. readonly 修饰的字段类型不限于那些具有字面量值的类型,而是所有数据类型

因为 readonly 可以将字段设为只读的,那么除字段声明和构造器方法之外,对其赋值,都会产生错误。所以,在代码中最好的方式就是不要直接对这样的字段做直接的读取,而是通过它的 get 属性,这样可以防止对它的意外赋值行为。这样的约束也是不难理解的,那么 C# 6.0 中新增的 只读自动属性 是不是顺其自然的事,其实它就是这种约束的语法糖。

参考资料:

posted @ 2020-09-20 23:32  Levid_GC  阅读(694)  评论(0编辑  收藏  举报